blob: bf761857c1c1e6d5d7a0c29b44acee8f5b934570 [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 Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200164 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100165 { NULL, 0, 0, 0 }
166};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167
Willy Tarreau6daf3432008-01-22 16:44:08 +0100168static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
170int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100171int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200173/* List head of all known configuration keywords */
174static struct cfg_kw_list cfg_keywords = {
175 .list = LIST_HEAD_INIT(cfg_keywords.list)
176};
177
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178/*
179 * converts <str> to a list of listeners which are dynamically allocated.
180 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
181 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
182 * - <port> is a numerical port from 1 to 65535 ;
183 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
184 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200185 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100187static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188{
189 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100190 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 int port, end;
192
193 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200194
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 while (next && *next) {
196 struct sockaddr_storage ss;
197
198 str = next;
199 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100200 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 *next++ = 0;
202 }
203
Emeric Bruned760922010-10-22 17:59:25 +0200204 if (*str == '/') {
205 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
206 /* so compute max path */
207 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
208 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 +0200209
Emeric Bruned760922010-10-22 17:59:25 +0200210 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
212 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200213 goto fail;
214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200217 ss.ss_family = AF_UNIX;
218 if (global.unix_bind.prefix) {
219 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
220 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 }
Emeric Bruned760922010-10-22 17:59:25 +0200222 else {
223 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
224 }
225 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 }
227 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 ss2 = str2sa_range(str, &port, &end);
231 if (!ss2) {
232 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
233 file, line, str);
234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 if (!port) {
238 Alert("parsing [%s:%d] : missing port number: '%s'\n",
239 file, line, str);
240 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100243 /* OK the address looks correct */
244 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Emeric Bruned760922010-10-22 17:59:25 +0200246 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
248 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
251
252 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
254 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257 }
258
259 for (; port <= end; port++) {
260 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200261 l->next = curproxy->listen;
262 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
264 l->fd = -1;
265 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100266 l->state = LI_INIT;
267
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100268 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100270 tcpv4_add_listener(l);
271 }
Emeric Bruned760922010-10-22 17:59:25 +0200272 else if (ss.ss_family == AF_INET6) {
273 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
274 tcpv6_add_listener(l);
275 }
276 else {
277 l->perm.ux.gid = l->perm.ux.uid = -1;
278 l->perm.ux.mode = 0;
279 uxst_add_listener(l);
280 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200281
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200282 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100283 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 } /* end for(port) */
285 } /* end while(next) */
286 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 fail:
289 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291}
292
Willy Tarreau977b8e42006-12-29 14:19:17 +0100293/*
294 * Sends a warning if proxy <proxy> does not have at least one of the
295 * capabilities in <cap>. An optionnal <hint> may be added at the end
296 * of the warning to help the user. Returns 1 if a warning was emitted
297 * or 0 if the condition is valid.
298 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100299int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100300{
301 char *msg;
302
303 switch (cap) {
304 case PR_CAP_BE: msg = "no backend"; break;
305 case PR_CAP_FE: msg = "no frontend"; break;
306 case PR_CAP_RS: msg = "no ruleset"; break;
307 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
308 default: msg = "not enough"; break;
309 }
310
311 if (!(proxy->cap & cap)) {
312 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100313 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100314 return 1;
315 }
316 return 0;
317}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318
Willy Tarreau61d18892009-03-31 10:49:21 +0200319/* Report a warning if a rule is placed after a 'block' rule.
320 * Return 1 if the warning has been emitted, otherwise 0.
321 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100322int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200323{
324 if (!LIST_ISEMPTY(&proxy->block_cond)) {
325 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
326 file, line, arg);
327 return 1;
328 }
329 return 0;
330}
331
332/* Report a warning if a rule is placed after a reqrewrite rule.
333 * Return 1 if the warning has been emitted, otherwise 0.
334 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100335int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200336{
337 if (proxy->req_exp) {
338 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
339 file, line, arg);
340 return 1;
341 }
342 return 0;
343}
344
345/* Report a warning if a rule is placed after a reqadd rule.
346 * Return 1 if the warning has been emitted, otherwise 0.
347 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100348int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200349{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100350 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200351 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
352 file, line, arg);
353 return 1;
354 }
355 return 0;
356}
357
358/* Report a warning if a rule is placed after a redirect rule.
359 * Return 1 if the warning has been emitted, otherwise 0.
360 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100361int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200362{
363 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
364 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
365 file, line, arg);
366 return 1;
367 }
368 return 0;
369}
370
371/* Report a warning if a rule is placed after a 'use_backend' rule.
372 * Return 1 if the warning has been emitted, otherwise 0.
373 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100374int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200375{
376 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
377 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
378 file, line, arg);
379 return 1;
380 }
381 return 0;
382}
383
384/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100385int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200386{
387 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
388 warnif_rule_after_reqadd(proxy, file, line, arg) ||
389 warnif_rule_after_redirect(proxy, file, line, arg) ||
390 warnif_rule_after_use_backend(proxy, file, line, arg);
391}
392
393/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
397 warnif_rule_after_redirect(proxy, file, line, arg) ||
398 warnif_rule_after_use_backend(proxy, file, line, arg);
399}
400
401/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 return warnif_rule_after_redirect(proxy, file, line, arg) ||
405 warnif_rule_after_use_backend(proxy, file, line, arg);
406}
407
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100408/* Report it if a request ACL condition uses some response-only parameters. It
409 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
410 * Note that <cond> may be NULL and then will be ignored.
411 */
412static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
413{
414 struct acl *acl;
415
416 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
417 return 0;
418
419 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
420 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
421 file, line, acl ? acl->name : "(unknown)");
422 return ERR_WARN;
423}
424
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100425/* Report it if a request ACL condition uses some request-only volatile parameters.
426 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
427 * Note that <cond> may be NULL and then will be ignored.
428 */
429static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
430{
431 struct acl *acl;
432
433 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
434 return 0;
435
436 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
437 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
438 file, line, acl ? acl->name : "(unknown)");
439 return ERR_WARN;
440}
441
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100442
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200444 * parse a line in a <global> section. Returns the error code, 0 if OK, or
445 * any combination of :
446 * - ERR_ABORT: must abort ASAP
447 * - ERR_FATAL: we can continue parsing but not start the service
448 * - ERR_WARN: a warning has been emitted
449 * - ERR_ALERT: an alert has been emitted
450 * Only the two first ones can stop processing, the two others are just
451 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200453int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454{
Willy Tarreau058e9072009-07-20 09:30:05 +0200455 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456
457 if (!strcmp(args[0], "global")) { /* new section */
458 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 }
461 else if (!strcmp(args[0], "daemon")) {
462 global.mode |= MODE_DAEMON;
463 }
464 else if (!strcmp(args[0], "debug")) {
465 global.mode |= MODE_DEBUG;
466 }
467 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100468 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200470 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100471 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200472 }
473 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100474 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100477 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100479 else if (!strcmp(args[0], "nosplice")) {
480 global.tune.options &= ~GTUNE_USE_SPLICE;
481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 else if (!strcmp(args[0], "quiet")) {
483 global.mode |= MODE_QUIET;
484 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200485 else if (!strcmp(args[0], "tune.maxpollevents")) {
486 if (global.tune.maxpollevents != 0) {
487 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200488 err_code |= ERR_ALERT;
489 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 err_code |= ERR_ALERT | ERR_FATAL;
494 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 }
496 global.tune.maxpollevents = atol(args[1]);
497 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100498 else if (!strcmp(args[0], "tune.maxaccept")) {
499 if (global.tune.maxaccept != 0) {
500 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200501 err_code |= ERR_ALERT;
502 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100503 }
504 if (*(args[1]) == 0) {
505 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 }
509 global.tune.maxaccept = atol(args[1]);
510 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200511 else if (!strcmp(args[0], "tune.chksize")) {
512 if (*(args[1]) == 0) {
513 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
514 err_code |= ERR_ALERT | ERR_FATAL;
515 goto out;
516 }
517 global.tune.chksize = atol(args[1]);
518 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200519 else if (!strcmp(args[0], "tune.bufsize")) {
520 if (*(args[1]) == 0) {
521 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
522 err_code |= ERR_ALERT | ERR_FATAL;
523 goto out;
524 }
525 global.tune.bufsize = atol(args[1]);
526 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
527 global.tune.maxrewrite = global.tune.bufsize / 2;
528 }
529 else if (!strcmp(args[0], "tune.maxrewrite")) {
530 if (*(args[1]) == 0) {
531 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
532 err_code |= ERR_ALERT | ERR_FATAL;
533 goto out;
534 }
535 global.tune.maxrewrite = atol(args[1]);
536 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
537 global.tune.maxrewrite = global.tune.bufsize / 2;
538 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100539 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
540 if (global.tune.client_rcvbuf != 0) {
541 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT;
543 goto out;
544 }
545 if (*(args[1]) == 0) {
546 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
547 err_code |= ERR_ALERT | ERR_FATAL;
548 goto out;
549 }
550 global.tune.client_rcvbuf = atol(args[1]);
551 }
552 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
553 if (global.tune.server_rcvbuf != 0) {
554 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
555 err_code |= ERR_ALERT;
556 goto out;
557 }
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.server_rcvbuf = atol(args[1]);
564 }
565 else if (!strcmp(args[0], "tune.sndbuf.client")) {
566 if (global.tune.client_sndbuf != 0) {
567 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT;
569 goto out;
570 }
571 if (*(args[1]) == 0) {
572 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT | ERR_FATAL;
574 goto out;
575 }
576 global.tune.client_sndbuf = atol(args[1]);
577 }
578 else if (!strcmp(args[0], "tune.sndbuf.server")) {
579 if (global.tune.server_sndbuf != 0) {
580 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT;
582 goto out;
583 }
584 if (*(args[1]) == 0) {
585 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588 }
589 global.tune.server_sndbuf = atol(args[1]);
590 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200591 else if (!strcmp(args[0], "tune.pipesize")) {
592 if (*(args[1]) == 0) {
593 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT | ERR_FATAL;
595 goto out;
596 }
597 global.tune.pipesize = atol(args[1]);
598 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200599 else if (!strcmp(args[0], "tune.http.maxhdr")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.max_http_hdr = atol(args[1]);
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 else if (!strcmp(args[0], "uid")) {
608 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 err_code |= ERR_ALERT;
611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 }
613 if (*(args[1]) == 0) {
614 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT | ERR_FATAL;
616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
618 global.uid = atol(args[1]);
619 }
620 else if (!strcmp(args[0], "gid")) {
621 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200622 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200623 err_code |= ERR_ALERT;
624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 }
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 }
631 global.gid = atol(args[1]);
632 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 /* user/group name handling */
634 else if (!strcmp(args[0], "user")) {
635 struct passwd *ha_user;
636 if (global.uid != 0) {
637 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_user = getpwnam(args[1]);
643 if (ha_user != NULL) {
644 global.uid = (int)ha_user->pw_uid;
645 }
646 else {
647 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 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 else if (!strcmp(args[0], "group")) {
652 struct group *ha_group;
653 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200654 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200657 }
658 errno = 0;
659 ha_group = getgrnam(args[1]);
660 if (ha_group != NULL) {
661 global.gid = (int)ha_group->gr_gid;
662 }
663 else {
664 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 +0200665 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200666 }
667 }
668 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 else if (!strcmp(args[0], "nbproc")) {
670 if (global.nbproc != 0) {
671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT;
673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
675 if (*(args[1]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 }
680 global.nbproc = atol(args[1]);
681 }
682 else if (!strcmp(args[0], "maxconn")) {
683 if (global.maxconn != 0) {
684 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200685 err_code |= ERR_ALERT;
686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 }
688 if (*(args[1]) == 0) {
689 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT | ERR_FATAL;
691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 global.maxconn = atol(args[1]);
694#ifdef SYSTEM_MAXCONN
695 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
696 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);
697 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 }
700#endif /* SYSTEM_MAXCONN */
701 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200702 else if (!strcmp(args[0], "maxconnrate")) {
703 if (global.cps_lim != 0) {
704 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT;
706 goto out;
707 }
708 if (*(args[1]) == 0) {
709 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 global.cps_lim = atol(args[1]);
714 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100715 else if (!strcmp(args[0], "maxpipes")) {
716 if (global.maxpipes != 0) {
717 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200718 err_code |= ERR_ALERT;
719 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100720 }
721 if (*(args[1]) == 0) {
722 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100725 }
726 global.maxpipes = atol(args[1]);
727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 else if (!strcmp(args[0], "ulimit-n")) {
729 if (global.rlimit_nofile != 0) {
730 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200731 err_code |= ERR_ALERT;
732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 }
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739 global.rlimit_nofile = atol(args[1]);
740 }
741 else if (!strcmp(args[0], "chroot")) {
742 if (global.chroot != NULL) {
743 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200744 err_code |= ERR_ALERT;
745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 }
747 if (*(args[1]) == 0) {
748 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 }
752 global.chroot = strdup(args[1]);
753 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200754 else if (!strcmp(args[0], "description")) {
755 int i, len=0;
756 char *d;
757
758 if (!*args[1]) {
759 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
760 file, linenum, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764
765 for(i=1; *args[i]; i++)
766 len += strlen(args[i])+1;
767
768 if (global.desc)
769 free(global.desc);
770
771 global.desc = d = (char *)calloc(1, len);
772
773 d += sprintf(d, "%s", args[1]);
774 for(i=2; *args[i]; i++)
775 d += sprintf(d, " %s", args[i]);
776 }
777 else if (!strcmp(args[0], "node")) {
778 int i;
779 char c;
780
781 for (i=0; args[1][i]; i++) {
782 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100783 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
784 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200785 break;
786 }
787
788 if (!i || args[1][i]) {
789 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
790 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
791 file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795
796 if (global.node)
797 free(global.node);
798
799 global.node = strdup(args[1]);
800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 else if (!strcmp(args[0], "pidfile")) {
802 if (global.pidfile != NULL) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200804 err_code |= ERR_ALERT;
805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 }
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 }
812 global.pidfile = strdup(args[1]);
813 }
Emeric Bruned760922010-10-22 17:59:25 +0200814 else if (!strcmp(args[0], "unix-bind")) {
815 int cur_arg = 1;
816 while (*(args[cur_arg])) {
817 if (!strcmp(args[cur_arg], "prefix")) {
818 if (global.unix_bind.prefix != NULL) {
819 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
820 err_code |= ERR_ALERT;
821 cur_arg += 2;
822 continue;
823 }
824
825 if (*(args[cur_arg+1]) == 0) {
826 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.unix_bind.prefix = strdup(args[cur_arg+1]);
831 cur_arg += 2;
832 continue;
833 }
834
835 if (!strcmp(args[cur_arg], "mode")) {
836
837 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "uid")) {
843
844 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
845 cur_arg += 2;
846 continue;
847 }
848
849 if (!strcmp(args[cur_arg], "gid")) {
850
851 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
852 cur_arg += 2;
853 continue;
854 }
855
856 if (!strcmp(args[cur_arg], "user")) {
857 struct passwd *user;
858
859 user = getpwnam(args[cur_arg + 1]);
860 if (!user) {
861 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
862 file, linenum, args[0], args[cur_arg + 1 ]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866
867 global.unix_bind.ux.uid = user->pw_uid;
868 cur_arg += 2;
869 continue;
870 }
871
872 if (!strcmp(args[cur_arg], "group")) {
873 struct group *group;
874
875 group = getgrnam(args[cur_arg + 1]);
876 if (!group) {
877 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
878 file, linenum, args[0], args[cur_arg + 1 ]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882
883 global.unix_bind.ux.gid = group->gr_gid;
884 cur_arg += 2;
885 continue;
886 }
887
Willy Tarreaub48f9582011-09-05 01:17:06 +0200888 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200889 file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100895 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200896 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897
898 if (*(args[1]) == 0 || *(args[2]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 }
903
904 facility = get_log_facility(args[2]);
905 if (facility < 0) {
906 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200907 err_code |= ERR_ALERT | ERR_FATAL;
908 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 }
910
911 level = 7; /* max syslog level = debug */
912 if (*(args[3])) {
913 level = get_log_level(args[3]);
914 if (level < 0) {
915 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
919 }
920
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200921 minlvl = 0; /* limit syslog level to this level (emerg) */
922 if (*(args[4])) {
923 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200925 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200926 err_code |= ERR_ALERT | ERR_FATAL;
927 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200928 }
929 }
930
Robert Tsai81ae1952007-12-05 10:47:29 +0100931 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100932 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100933 if (!sk) {
934 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100935 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100939 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100940 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100941 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100942 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100943 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
944 err_code |= ERR_ALERT | ERR_FATAL;
945 goto out;
946 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100947 logsrv.addr = *sk;
948 if (!get_host_port(&logsrv.addr))
949 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951
952 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100953 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 global.logfac1 = facility;
955 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200956 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960 global.logfac2 = facility;
961 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200962 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 else {
965 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200968 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100969 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
970 char *name;
971 int len;
972
973 if (global.log_send_hostname != NULL) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
975 err_code |= ERR_ALERT;
976 goto out;
977 }
978
979 if (*(args[1]))
980 name = args[1];
981 else
982 name = hostname;
983
984 len = strlen(name);
985
986 /* We'll add a space after the name to respect the log format */
987 free(global.log_send_hostname);
988 global.log_send_hostname = malloc(len + 2);
989 snprintf(global.log_send_hostname, len + 2, "%s ", name);
990 }
Kevinm48936af2010-12-22 16:08:21 +0000991 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
992 if (*(args[1]) == 0) {
993 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
994 err_code |= ERR_ALERT | ERR_FATAL;
995 goto out;
996 }
997 free(global.log_tag);
998 global.log_tag = strdup(args[1]);
999 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001000 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1001 if (global.spread_checks != 0) {
1002 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT;
1004 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 }
1006 if (*(args[1]) == 0) {
1007 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 global.spread_checks = atol(args[1]);
1012 if (global.spread_checks < 0 || global.spread_checks > 50) {
1013 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
1017 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001018 struct cfg_kw_list *kwl;
1019 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001020 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001021
1022 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1023 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1024 if (kwl->kw[index].section != CFG_GLOBAL)
1025 continue;
1026 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1027 /* prepare error message just in case */
1028 snprintf(trash, sizeof(trash),
1029 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001030 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1031 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001032 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001033 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001034 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 else if (rc > 0) {
1036 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_WARN;
1038 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001039 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001041 }
1042 }
1043 }
1044
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001046 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001047 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001048
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 out:
1050 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051}
1052
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001053void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001055 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 defproxy.mode = PR_MODE_TCP;
1057 defproxy.state = PR_STNEW;
1058 defproxy.maxconn = cfg_maxpconn;
1059 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001060
1061 defproxy.defsrv.inter = DEF_CHKINTR;
1062 defproxy.defsrv.fastinter = 0;
1063 defproxy.defsrv.downinter = 0;
1064 defproxy.defsrv.rise = DEF_RISETIME;
1065 defproxy.defsrv.fall = DEF_FALLTIME;
1066 defproxy.defsrv.check_port = 0;
1067 defproxy.defsrv.maxqueue = 0;
1068 defproxy.defsrv.minconn = 0;
1069 defproxy.defsrv.maxconn = 0;
1070 defproxy.defsrv.slowstart = 0;
1071 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1072 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1073 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074}
1075
Willy Tarreauade5ec42010-01-28 19:33:49 +01001076
1077static int create_cond_regex_rule(const char *file, int line,
1078 struct proxy *px, int dir, int action, int flags,
1079 const char *cmd, const char *reg, const char *repl,
1080 const char **cond_start)
1081{
1082 regex_t *preg = NULL;
1083 const char *err;
1084 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001085 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001086
1087 if (px == &defproxy) {
1088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto err;
1091 }
1092
1093 if (*reg == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto err;
1097 }
1098
1099 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1100 err_code |= ERR_WARN;
1101
Willy Tarreau5321c422010-01-28 20:35:13 +01001102 if (cond_start &&
1103 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1104 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1105 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1106 file, line, cmd);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto err;
1109 }
1110 }
1111 else if (cond_start && **cond_start) {
1112 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1113 file, line, cmd, *cond_start);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto err;
1116 }
1117
1118 if (dir == ACL_DIR_REQ)
1119 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001120 else
1121 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001122
Willy Tarreauade5ec42010-01-28 19:33:49 +01001123 preg = calloc(1, sizeof(regex_t));
1124 if (!preg) {
1125 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1126 err_code = ERR_ALERT | ERR_FATAL;
1127 goto err;
1128 }
1129
1130 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1131 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1132 err_code = ERR_ALERT | ERR_FATAL;
1133 goto err;
1134 }
1135
1136 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001137 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001138 if (repl && err) {
1139 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1140 file, line, cmd, *err);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto err;
1143 }
1144
1145 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1146 err_code |= ERR_WARN;
1147
1148 return err_code;
1149 err:
1150 free(preg);
1151 return err_code;
1152}
1153
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001155 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001156 * Returns the error code, 0 if OK, or any combination of :
1157 * - ERR_ABORT: must abort ASAP
1158 * - ERR_FATAL: we can continue parsing but not start the service
1159 * - ERR_WARN: a warning has been emitted
1160 * - ERR_ALERT: an alert has been emitted
1161 * Only the two first ones can stop processing, the two others are just
1162 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001164int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1165{
1166 static struct peers *curpeers = NULL;
1167 struct peer *newpeer = NULL;
1168 const char *err;
1169 int err_code = 0;
1170
1171 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1172
1173 err = invalid_char(args[1]);
1174 if (err) {
1175 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1176 file, linenum, *err, args[0], args[1]);
1177 err_code |= ERR_ALERT | ERR_FATAL;
1178 }
1179
1180 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1181 /*
1182 * If there are two proxies with the same name only following
1183 * combinations are allowed:
1184 */
1185 if (strcmp(curpeers->id, args[1]) == 0) {
1186 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1187 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1188 err_code |= ERR_WARN;
1189 }
1190 }
1191
1192 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1193 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1194 err_code |= ERR_ALERT | ERR_ABORT;
1195 goto out;
1196 }
1197
1198 curpeers->next = peers;
1199 peers = curpeers;
1200 curpeers->conf.file = file;
1201 curpeers->conf.line = linenum;
1202 curpeers->last_change = now.tv_sec;
1203 curpeers->id = strdup(args[1]);
1204 }
1205 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1206 char *rport, *raddr;
1207 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001208 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001209
1210 if (!*args[2]) {
1211 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1212 file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216
1217 err = invalid_char(args[1]);
1218 if (err) {
1219 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1220 file, linenum, *err, args[1]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224
1225 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1227 err_code |= ERR_ALERT | ERR_ABORT;
1228 goto out;
1229 }
1230
1231 /* the peers are linked backwards first */
1232 curpeers->count++;
1233 newpeer->next = curpeers->remote;
1234 curpeers->remote = newpeer;
1235 newpeer->peers = curpeers;
1236 newpeer->conf.file = file;
1237 newpeer->conf.line = linenum;
1238
1239 newpeer->last_change = now.tv_sec;
1240 newpeer->id = strdup(args[1]);
1241
1242 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001243 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001244 if (rport) {
1245 *rport++ = 0;
1246 realport = atol(rport);
1247 }
1248 if (!realport) {
1249 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253
Willy Tarreaufab5a432011-03-04 15:31:53 +01001254 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001255 free(raddr);
1256 if (!sk) {
1257 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001262 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001263
1264 if (strcmp(newpeer->id, localpeer) == 0) {
1265 /* Current is local peer, it define a frontend */
1266 newpeer->local = 1;
1267
1268 if (!curpeers->peers_fe) {
1269 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1270 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1271 err_code |= ERR_ALERT | ERR_ABORT;
1272 goto out;
1273 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001274
Willy Tarreau237250c2011-07-29 01:49:03 +02001275 init_new_proxy(curpeers->peers_fe);
1276 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001277
1278 curpeers->peers_fe->last_change = now.tv_sec;
1279 curpeers->peers_fe->id = strdup(args[1]);
1280 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001281 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001282 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1283 curpeers->peers_fe->timeout.connect = 5000;
1284 curpeers->peers_fe->accept = peer_accept;
1285 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001286 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001287 err_code |= ERR_FATAL;
1288 goto out;
1289 }
1290 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1291 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1292 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1293 curpeers->peers_fe->listen->accept = session_accept;
1294 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1295 curpeers->peers_fe->listen->handler = process_session;
1296 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001297 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1298 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001299 }
1300 }
1301 } /* neither "peer" nor "peers" */
1302 else if (*args[0] != 0) {
1303 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1304 err_code |= ERR_ALERT | ERR_FATAL;
1305 goto out;
1306 }
1307
1308out:
1309 return err_code;
1310}
1311
1312
Willy Tarreau3842f002009-06-14 11:39:52 +02001313int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314{
1315 static struct proxy *curproxy = NULL;
1316 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001317 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001318 int rc;
1319 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001320 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001321 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322
Willy Tarreau977b8e42006-12-29 14:19:17 +01001323 if (!strcmp(args[0], "listen"))
1324 rc = PR_CAP_LISTEN;
1325 else if (!strcmp(args[0], "frontend"))
1326 rc = PR_CAP_FE | PR_CAP_RS;
1327 else if (!strcmp(args[0], "backend"))
1328 rc = PR_CAP_BE | PR_CAP_RS;
1329 else if (!strcmp(args[0], "ruleset"))
1330 rc = PR_CAP_RS;
1331 else
1332 rc = PR_CAP_NONE;
1333
1334 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001335 if (!*args[1]) {
1336 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1337 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001339 err_code |= ERR_ALERT | ERR_ABORT;
1340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001342
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001343 err = invalid_char(args[1]);
1344 if (err) {
1345 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1346 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001348 }
1349
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001350 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1351 /*
1352 * If there are two proxies with the same name only following
1353 * combinations are allowed:
1354 *
1355 * listen backend frontend ruleset
1356 * listen - - - -
1357 * backend - - OK -
1358 * frontend - OK - -
1359 * ruleset - - - -
1360 */
1361
1362 if (!strcmp(curproxy->id, args[1]) &&
1363 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1364 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001365 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1366 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1367 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001368 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001369 }
1370 }
1371
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1373 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_ALERT | ERR_ABORT;
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001377
Willy Tarreau97cb7802010-01-03 20:23:58 +01001378 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 curproxy->next = proxy;
1380 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001381 curproxy->conf.file = file;
1382 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001383 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001385 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386
1387 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001388 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001389 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001390 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001391 err_code |= ERR_FATAL;
1392 goto out;
1393 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001394 new = curproxy->listen;
1395 while (new != last) {
1396 new->conf.file = file;
1397 new->conf.line = linenum;
1398 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001399 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 }
1402
1403 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001404 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001405 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001406
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001409 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001410 curproxy->no_options = defproxy.no_options;
1411 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001412 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001413 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001414 curproxy->except_net = defproxy.except_net;
1415 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001416 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001417 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001419 if (defproxy.fwdfor_hdr_len) {
1420 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1421 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1422 }
1423
Willy Tarreaub86db342009-11-30 11:50:16 +01001424 if (defproxy.orgto_hdr_len) {
1425 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1426 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1427 }
1428
Willy Tarreau977b8e42006-12-29 14:19:17 +01001429 if (curproxy->cap & PR_CAP_FE) {
1430 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001431 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001432 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001433
1434 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001435 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1436 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001437
1438 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001440
Willy Tarreau977b8e42006-12-29 14:19:17 +01001441 if (curproxy->cap & PR_CAP_BE) {
1442 curproxy->fullconn = defproxy.fullconn;
1443 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001444
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001445 if (defproxy.check_req) {
1446 curproxy->check_req = calloc(1, defproxy.check_len);
1447 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1448 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001449 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001451 if (defproxy.expect_str) {
1452 curproxy->expect_str = strdup(defproxy.expect_str);
1453 if (defproxy.expect_regex) {
1454 /* note: this regex is known to be valid */
1455 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1456 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1457 }
1458 }
1459
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460 if (defproxy.cookie_name)
1461 curproxy->cookie_name = strdup(defproxy.cookie_name);
1462 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001463 if (defproxy.cookie_domain)
1464 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001465
Willy Tarreau31936852010-10-06 16:59:56 +02001466 if (defproxy.cookie_maxidle)
1467 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1468
1469 if (defproxy.cookie_maxlife)
1470 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1471
Emeric Brun647caf12009-06-30 17:57:00 +02001472 if (defproxy.rdp_cookie_name)
1473 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1474 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1475
Willy Tarreau01732802007-11-01 22:48:15 +01001476 if (defproxy.url_param_name)
1477 curproxy->url_param_name = strdup(defproxy.url_param_name);
1478 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001479
Benoitaffb4812009-03-25 13:02:10 +01001480 if (defproxy.hh_name)
1481 curproxy->hh_name = strdup(defproxy.hh_name);
1482 curproxy->hh_len = defproxy.hh_len;
1483 curproxy->hh_match_domain = defproxy.hh_match_domain;
1484
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001485 if (defproxy.iface_name)
1486 curproxy->iface_name = strdup(defproxy.iface_name);
1487 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001488 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001490 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001491 if (defproxy.capture_name)
1492 curproxy->capture_name = strdup(defproxy.capture_name);
1493 curproxy->capture_namelen = defproxy.capture_namelen;
1494 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001495 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001498 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001499 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001500 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001501 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502 curproxy->uri_auth = defproxy.uri_auth;
1503 curproxy->mon_net = defproxy.mon_net;
1504 curproxy->mon_mask = defproxy.mon_mask;
1505 if (defproxy.monitor_uri)
1506 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1507 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001508 if (defproxy.defbe.name)
1509 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001510 }
1511
1512 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001513 curproxy->timeout.connect = defproxy.timeout.connect;
1514 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001515 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001516 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001517 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001518 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001519 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520 curproxy->source_addr = defproxy.source_addr;
1521 }
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 curproxy->mode = defproxy.mode;
1524 curproxy->logfac1 = defproxy.logfac1;
1525 curproxy->logsrv1 = defproxy.logsrv1;
1526 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001527 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 curproxy->logfac2 = defproxy.logfac2;
1529 curproxy->logsrv2 = defproxy.logsrv2;
1530 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001531 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001533 curproxy->conf.used_listener_id = EB_ROOT;
1534 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001535
Willy Tarreau93893792009-07-23 13:19:11 +02001536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 }
1538 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1539 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001540 /* FIXME-20070101: we should do this too at the end of the
1541 * config parsing to free all default values.
1542 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001543 free(defproxy.check_req);
1544 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001545 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001546 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001547 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001548 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001549 free(defproxy.capture_name);
1550 free(defproxy.monitor_uri);
1551 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001552 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001553 free(defproxy.fwdfor_hdr_name);
1554 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001555 free(defproxy.orgto_hdr_name);
1556 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001557 free(defproxy.expect_str);
1558 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001559
Willy Tarreaua534fea2008-08-03 12:19:50 +02001560 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001561 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001562
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 /* we cannot free uri_auth because it might already be used */
1564 init_default_instance();
1565 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001566 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 }
1569 else if (curproxy == NULL) {
1570 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 }
1574
Willy Tarreau977b8e42006-12-29 14:19:17 +01001575
1576 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001578 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001579 int cur_arg;
1580
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 if (curproxy == &defproxy) {
1582 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001583 err_code |= ERR_ALERT | ERR_FATAL;
1584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001586 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001587 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588
Emeric Bruned760922010-10-22 17:59:25 +02001589 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001590 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001592 err_code |= ERR_ALERT | ERR_FATAL;
1593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001595
1596 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001597
1598 /* NOTE: the following line might create several listeners if there
1599 * are comma-separated IPs or port ranges. So all further processing
1600 * will have to be applied to all listeners created after last_listen.
1601 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001602 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001603 err_code |= ERR_ALERT | ERR_FATAL;
1604 goto out;
1605 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001606
Willy Tarreau90a570f2009-10-04 20:54:54 +02001607 new_listen = curproxy->listen;
1608 while (new_listen != last_listen) {
1609 new_listen->conf.file = file;
1610 new_listen->conf.line = linenum;
1611 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001612 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001613 }
1614
Emeric Bruned760922010-10-22 17:59:25 +02001615 /* Set default global rights and owner for unix bind */
1616 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1617 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1618 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001619 cur_arg = 2;
1620 while (*(args[cur_arg])) {
1621 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1622#ifdef SO_BINDTODEVICE
1623 struct listener *l;
1624
Emeric Bruned760922010-10-22 17:59:25 +02001625 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1626 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1627 file, linenum, args[0], args[cur_arg]);
1628 err_code |= ERR_ALERT | ERR_FATAL;
1629 goto out;
1630 }
1631
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001632 if (!*args[cur_arg + 1]) {
1633 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001635 err_code |= ERR_ALERT | ERR_FATAL;
1636 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001637 }
1638
1639 for (l = curproxy->listen; l != last_listen; l = l->next)
1640 l->interface = strdup(args[cur_arg + 1]);
1641
1642 global.last_checks |= LSTCHK_NETADM;
1643
1644 cur_arg += 2;
1645 continue;
1646#else
1647 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1648 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001649 err_code |= ERR_ALERT | ERR_FATAL;
1650 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001651#endif
1652 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001653 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1654#ifdef TCP_MAXSEG
1655 struct listener *l;
1656 int mss;
1657
Emeric Bruned760922010-10-22 17:59:25 +02001658 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1659 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1660 file, linenum, args[0], args[cur_arg]);
1661 err_code |= ERR_ALERT | ERR_FATAL;
1662 goto out;
1663 }
1664
Willy Tarreaube1b9182009-06-14 18:48:19 +02001665 if (!*args[cur_arg + 1]) {
1666 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001670 }
1671
Willy Tarreau48a7e722010-12-24 15:26:39 +01001672 mss = atoi(args[cur_arg + 1]);
1673 if (!mss || abs(mss) > 65535) {
1674 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001675 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001676 err_code |= ERR_ALERT | ERR_FATAL;
1677 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001678 }
1679
1680 for (l = curproxy->listen; l != last_listen; l = l->next)
1681 l->maxseg = mss;
1682
1683 cur_arg += 2;
1684 continue;
1685#else
1686 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1687 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001690#endif
1691 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001692
1693 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1694#ifdef TCP_DEFER_ACCEPT
1695 struct listener *l;
1696
1697 for (l = curproxy->listen; l != last_listen; l = l->next)
1698 l->options |= LI_O_DEF_ACCEPT;
1699
1700 cur_arg ++;
1701 continue;
1702#else
1703 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1704 file, linenum, args[0], args[cur_arg]);
1705 err_code |= ERR_ALERT | ERR_FATAL;
1706 goto out;
1707#endif
1708 }
1709
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001710 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001711#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001712 struct listener *l;
1713
Emeric Bruned760922010-10-22 17:59:25 +02001714 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1715 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1716 file, linenum, args[0], args[cur_arg]);
1717 err_code |= ERR_ALERT | ERR_FATAL;
1718 goto out;
1719 }
1720
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001721 for (l = curproxy->listen; l != last_listen; l = l->next)
1722 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001723
1724 cur_arg ++;
1725 continue;
1726#else
1727 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1728 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001731#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001732 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001733
Willy Tarreau8a956912010-10-15 14:27:08 +02001734 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1735 struct listener *l;
1736
1737 for (l = curproxy->listen; l != last_listen; l = l->next)
1738 l->options |= LI_O_ACC_PROXY;
1739
1740 cur_arg ++;
1741 continue;
1742 }
1743
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001744 if (!strcmp(args[cur_arg], "name")) {
1745 struct listener *l;
1746
1747 for (l = curproxy->listen; l != last_listen; l = l->next)
1748 l->name = strdup(args[cur_arg + 1]);
1749
1750 cur_arg += 2;
1751 continue;
1752 }
1753
1754 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001755 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001756 struct listener *l;
1757
1758 if (curproxy->listen->next != last_listen) {
1759 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1760 file, linenum, args[cur_arg]);
1761 err_code |= ERR_ALERT | ERR_FATAL;
1762 goto out;
1763 }
1764
1765 if (!*args[cur_arg + 1]) {
1766 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1767 file, linenum, args[cur_arg]);
1768 err_code |= ERR_ALERT | ERR_FATAL;
1769 goto out;
1770 }
1771
1772 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001773 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001774
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001775 if (curproxy->listen->luid <= 0) {
1776 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001777 file, linenum);
1778 err_code |= ERR_ALERT | ERR_FATAL;
1779 goto out;
1780 }
1781
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001782 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1783 if (node) {
1784 l = container_of(node, struct listener, conf.id);
1785 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1786 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1787 err_code |= ERR_ALERT | ERR_FATAL;
1788 goto out;
1789 }
1790 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1791
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001792 cur_arg += 2;
1793 continue;
1794 }
1795
Emeric Bruned760922010-10-22 17:59:25 +02001796 if (!strcmp(args[cur_arg], "mode")) {
1797
1798 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1799 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1800 file, linenum, args[0], args[cur_arg]);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804
1805 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1806
1807 cur_arg += 2;
1808 continue;
1809 }
1810
1811 if (!strcmp(args[cur_arg], "uid")) {
1812
1813 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1814 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1815 file, linenum, args[0], args[cur_arg]);
1816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
1819
1820 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1821 cur_arg += 2;
1822 continue;
1823 }
1824
1825 if (!strcmp(args[cur_arg], "gid")) {
1826
1827 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1828 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1829 file, linenum, args[0], args[cur_arg]);
1830 err_code |= ERR_ALERT | ERR_FATAL;
1831 goto out;
1832 }
1833
1834 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1835 cur_arg += 2;
1836 continue;
1837 }
1838
1839 if (!strcmp(args[cur_arg], "user")) {
1840 struct passwd *user;
1841
1842 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1843 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1844 file, linenum, args[0], args[cur_arg]);
1845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
1847 }
1848 user = getpwnam(args[cur_arg + 1]);
1849 if (!user) {
1850 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1851 file, linenum, args[0], args[cur_arg + 1 ]);
1852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
1854 }
1855
1856 curproxy->listen->perm.ux.uid = user->pw_uid;
1857 cur_arg += 2;
1858 continue;
1859 }
1860
1861 if (!strcmp(args[cur_arg], "group")) {
1862 struct group *group;
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 group = getgrnam(args[cur_arg + 1]);
1871 if (!group) {
1872 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1873 file, linenum, args[0], args[cur_arg + 1 ]);
1874 err_code |= ERR_ALERT | ERR_FATAL;
1875 goto out;
1876 }
1877
1878 curproxy->listen->perm.ux.gid = group->gr_gid;
1879 cur_arg += 2;
1880 continue;
1881 }
1882
Willy Tarreaub48f9582011-09-05 01:17:06 +02001883 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 +01001884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001887 }
Willy Tarreau93893792009-07-23 13:19:11 +02001888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889 }
1890 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1891 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1892 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1893 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001898 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 /* flush useless bits */
1901 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001904 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001905 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001906 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907
Willy Tarreau1c47f852006-07-09 08:22:27 +02001908 if (!*args[1]) {
1909 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1910 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001911 err_code |= ERR_ALERT | ERR_FATAL;
1912 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001913 }
1914
Willy Tarreaua534fea2008-08-03 12:19:50 +02001915 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001916 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001917 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001918 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001919 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1920
Willy Tarreau93893792009-07-23 13:19:11 +02001921 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1924 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1925 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1926 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1927 else {
1928 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
1932 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001933 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001934 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001935
1936 if (curproxy == &defproxy) {
1937 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
1940 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001941 }
1942
1943 if (!*args[1]) {
1944 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1945 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001948 }
1949
1950 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001951 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001952
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001953 if (curproxy->uuid <= 0) {
1954 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001955 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001958 }
1959
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001960 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1961 if (node) {
1962 struct proxy *target = container_of(node, struct proxy, conf.id);
1963 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1964 file, linenum, proxy_type_str(curproxy), curproxy->id,
1965 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1966 err_code |= ERR_ALERT | ERR_FATAL;
1967 goto out;
1968 }
1969 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001970 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001971 else if (!strcmp(args[0], "description")) {
1972 int i, len=0;
1973 char *d;
1974
Cyril Bonté99ed3272010-01-24 23:29:44 +01001975 if (curproxy == &defproxy) {
1976 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1977 file, linenum, args[0]);
1978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
1980 }
1981
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001982 if (!*args[1]) {
1983 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1984 file, linenum, args[0]);
1985 return -1;
1986 }
1987
1988 for(i=1; *args[i]; i++)
1989 len += strlen(args[i])+1;
1990
1991 d = (char *)calloc(1, len);
1992 curproxy->desc = d;
1993
1994 d += sprintf(d, "%s", args[1]);
1995 for(i=2; *args[i]; i++)
1996 d += sprintf(d, " %s", args[i]);
1997
1998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2000 curproxy->state = PR_STSTOPPED;
2001 }
2002 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2003 curproxy->state = PR_STNEW;
2004 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002005 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2006 int cur_arg = 1;
2007 unsigned int set = 0;
2008
2009 while (*args[cur_arg]) {
2010 int u;
2011 if (strcmp(args[cur_arg], "all") == 0) {
2012 set = 0;
2013 break;
2014 }
2015 else if (strcmp(args[cur_arg], "odd") == 0) {
2016 set |= 0x55555555;
2017 }
2018 else if (strcmp(args[cur_arg], "even") == 0) {
2019 set |= 0xAAAAAAAA;
2020 }
2021 else {
2022 u = str2uic(args[cur_arg]);
2023 if (u < 1 || u > 32) {
2024 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2025 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002028 }
2029 if (u > global.nbproc) {
2030 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002033 }
2034 set |= 1 << (u - 1);
2035 }
2036 cur_arg++;
2037 }
2038 curproxy->bind_proc = set;
2039 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002040 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002041 if (curproxy == &defproxy) {
2042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_ALERT | ERR_FATAL;
2044 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002045 }
2046
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002047 err = invalid_char(args[1]);
2048 if (err) {
2049 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2050 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002052 }
2053
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002054 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2055 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2056 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002059 }
2060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2062 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002066
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 if (*(args[1]) == 0) {
2068 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2069 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002073
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002074 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002075 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002076 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002077 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002078 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079 curproxy->cookie_name = strdup(args[1]);
2080 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002081
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 cur_arg = 2;
2083 while (*(args[cur_arg])) {
2084 if (!strcmp(args[cur_arg], "rewrite")) {
2085 curproxy->options |= PR_O_COOK_RW;
2086 }
2087 else if (!strcmp(args[cur_arg], "indirect")) {
2088 curproxy->options |= PR_O_COOK_IND;
2089 }
2090 else if (!strcmp(args[cur_arg], "insert")) {
2091 curproxy->options |= PR_O_COOK_INS;
2092 }
2093 else if (!strcmp(args[cur_arg], "nocache")) {
2094 curproxy->options |= PR_O_COOK_NOC;
2095 }
2096 else if (!strcmp(args[cur_arg], "postonly")) {
2097 curproxy->options |= PR_O_COOK_POST;
2098 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002099 else if (!strcmp(args[cur_arg], "preserve")) {
2100 curproxy->options2 |= PR_O2_COOK_PSV;
2101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 else if (!strcmp(args[cur_arg], "prefix")) {
2103 curproxy->options |= PR_O_COOK_PFX;
2104 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002105 else if (!strcmp(args[cur_arg], "domain")) {
2106 if (!*args[cur_arg + 1]) {
2107 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2108 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
2110 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002111 }
2112
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002113 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002114 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002115 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2116 " dots nor does not start with a dot."
2117 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002118 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002119 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002120 }
2121
2122 err = invalid_domainchar(args[cur_arg + 1]);
2123 if (err) {
2124 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2125 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002128 }
2129
Willy Tarreau68a897b2009-12-03 23:28:34 +01002130 if (!curproxy->cookie_domain) {
2131 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2132 } else {
2133 /* one domain was already specified, add another one by
2134 * building the string which will be returned along with
2135 * the cookie.
2136 */
2137 char *new_ptr;
2138 int new_len = strlen(curproxy->cookie_domain) +
2139 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2140 new_ptr = malloc(new_len);
2141 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2142 free(curproxy->cookie_domain);
2143 curproxy->cookie_domain = new_ptr;
2144 }
Willy Tarreau31936852010-10-06 16:59:56 +02002145 cur_arg++;
2146 }
2147 else if (!strcmp(args[cur_arg], "maxidle")) {
2148 unsigned int maxidle;
2149 const char *res;
2150
2151 if (!*args[cur_arg + 1]) {
2152 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2153 file, linenum, args[cur_arg]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
2157
2158 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2159 if (res) {
2160 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2161 file, linenum, *res, args[cur_arg]);
2162 err_code |= ERR_ALERT | ERR_FATAL;
2163 goto out;
2164 }
2165 curproxy->cookie_maxidle = maxidle;
2166 cur_arg++;
2167 }
2168 else if (!strcmp(args[cur_arg], "maxlife")) {
2169 unsigned int maxlife;
2170 const char *res;
2171
2172 if (!*args[cur_arg + 1]) {
2173 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2174 file, linenum, args[cur_arg]);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178
2179 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2180 if (res) {
2181 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2182 file, linenum, *res, args[cur_arg]);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
2186 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002187 cur_arg++;
2188 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002190 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 +02002191 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194 }
2195 cur_arg++;
2196 }
2197 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2198 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2199 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002200 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 }
2202
2203 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2204 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2205 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002206 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002208
2209 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2210 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2211 file, linenum);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002214 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002215 else if (!strcmp(args[0], "persist")) { /* persist */
2216 if (*(args[1]) == 0) {
2217 Alert("parsing [%s:%d] : missing persist method.\n",
2218 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
2220 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002221 }
2222
2223 if (!strncmp(args[1], "rdp-cookie", 10)) {
2224 curproxy->options2 |= PR_O2_RDPC_PRST;
2225
Emeric Brunb982a3d2010-01-04 15:45:53 +01002226 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002227 const char *beg, *end;
2228
2229 beg = args[1] + 11;
2230 end = strchr(beg, ')');
2231
2232 if (!end || end == beg) {
2233 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2234 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
2236 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002237 }
2238
2239 free(curproxy->rdp_cookie_name);
2240 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2241 curproxy->rdp_cookie_len = end-beg;
2242 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002243 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002244 free(curproxy->rdp_cookie_name);
2245 curproxy->rdp_cookie_name = strdup("msts");
2246 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2247 }
2248 else { /* syntax */
2249 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2250 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002251 err_code |= ERR_ALERT | ERR_FATAL;
2252 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002253 }
2254 }
2255 else {
2256 Alert("parsing [%s:%d] : unknown persist method.\n",
2257 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002260 }
2261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002262 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002263 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002265 if (curproxy == &defproxy) {
2266 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2267 err_code |= ERR_ALERT | ERR_FATAL;
2268 goto out;
2269 }
2270
Willy Tarreau977b8e42006-12-29 14:19:17 +01002271 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002275 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
2280 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002281 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 curproxy->appsession_name = strdup(args[1]);
2283 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2284 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002285 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2286 if (err) {
2287 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2288 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002291 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002292 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002293
Willy Tarreau51041c72007-09-09 21:56:53 +02002294 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2295 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002296 err_code |= ERR_ALERT | ERR_ABORT;
2297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002299
2300 cur_arg = 6;
2301 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002302 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2303 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002304 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002305 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002306 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002307 } else if (!strcmp(args[cur_arg], "prefix")) {
2308 curproxy->options2 |= PR_O2_AS_PFX;
2309 } else if (!strcmp(args[cur_arg], "mode")) {
2310 if (!*args[cur_arg + 1]) {
2311 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2312 file, linenum, args[0], args[cur_arg]);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316
2317 cur_arg++;
2318 if (!strcmp(args[cur_arg], "query-string")) {
2319 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2320 curproxy->options2 |= PR_O2_AS_M_QS;
2321 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2322 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2323 curproxy->options2 |= PR_O2_AS_M_PP;
2324 } else {
2325 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002330 cur_arg++;
2331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 } /* Url App Session */
2333 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002334 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002335 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002336
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002338 if (curproxy == &defproxy) {
2339 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
2343
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 if (*(args[4]) == 0) {
2345 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2346 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002350 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 curproxy->capture_name = strdup(args[2]);
2352 curproxy->capture_namelen = strlen(curproxy->capture_name);
2353 curproxy->capture_len = atol(args[4]);
2354 if (curproxy->capture_len >= CAPTURE_LEN) {
2355 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2356 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002358 curproxy->capture_len = CAPTURE_LEN - 1;
2359 }
2360 curproxy->to_log |= LW_COOKIE;
2361 }
2362 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2363 struct cap_hdr *hdr;
2364
2365 if (curproxy == &defproxy) {
2366 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 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
2370
2371 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2372 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2373 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
2375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 }
2377
2378 hdr = calloc(sizeof(struct cap_hdr), 1);
2379 hdr->next = curproxy->req_cap;
2380 hdr->name = strdup(args[3]);
2381 hdr->namelen = strlen(args[3]);
2382 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002383 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 hdr->index = curproxy->nb_req_cap++;
2385 curproxy->req_cap = hdr;
2386 curproxy->to_log |= LW_REQHDR;
2387 }
2388 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2389 struct cap_hdr *hdr;
2390
2391 if (curproxy == &defproxy) {
2392 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 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
2396
2397 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2398 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2399 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
2403 hdr = calloc(sizeof(struct cap_hdr), 1);
2404 hdr->next = curproxy->rsp_cap;
2405 hdr->name = strdup(args[3]);
2406 hdr->namelen = strlen(args[3]);
2407 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002408 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 hdr->index = curproxy->nb_rsp_cap++;
2410 curproxy->rsp_cap = hdr;
2411 curproxy->to_log |= LW_RSPHDR;
2412 }
2413 else {
2414 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2415 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 }
2419 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002421 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 if (*(args[1]) == 0) {
2425 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2426 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
2430 curproxy->conn_retries = atol(args[1]);
2431 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002432 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002433 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002434
2435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
2439 }
2440
Willy Tarreauff011f22011-01-06 17:51:27 +01002441 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 +01002442 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2443 file, linenum, args[0]);
2444 err_code |= ERR_WARN;
2445 }
2446
Willy Tarreauff011f22011-01-06 17:51:27 +01002447 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002448
Willy Tarreauff011f22011-01-06 17:51:27 +01002449 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002450 err_code |= ERR_ALERT | ERR_ABORT;
2451 goto out;
2452 }
2453
Willy Tarreauff011f22011-01-06 17:51:27 +01002454 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2455 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002456 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002457 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002458 if (curproxy == &defproxy) {
2459 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002462 }
2463
Willy Tarreauef6494c2010-01-28 17:12:36 +01002464 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002465 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2466 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002469 }
2470
Willy Tarreauef6494c2010-01-28 17:12:36 +01002471 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002472 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2473 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002476 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002477
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002478 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002479 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002480 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002481 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002482 struct redirect_rule *rule;
2483 int cur_arg;
2484 int type = REDIRECT_TYPE_NONE;
2485 int code = 302;
2486 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002487 char *cookie = NULL;
2488 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002489 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002490
Cyril Bonté99ed3272010-01-24 23:29:44 +01002491 if (curproxy == &defproxy) {
2492 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
2495 }
2496
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002497 cur_arg = 1;
2498 while (*(args[cur_arg])) {
2499 if (!strcmp(args[cur_arg], "location")) {
2500 if (!*args[cur_arg + 1]) {
2501 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2502 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002505 }
2506
2507 type = REDIRECT_TYPE_LOCATION;
2508 cur_arg++;
2509 destination = args[cur_arg];
2510 }
2511 else if (!strcmp(args[cur_arg], "prefix")) {
2512 if (!*args[cur_arg + 1]) {
2513 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2514 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002517 }
2518
2519 type = REDIRECT_TYPE_PREFIX;
2520 cur_arg++;
2521 destination = args[cur_arg];
2522 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002523 else if (!strcmp(args[cur_arg], "set-cookie")) {
2524 if (!*args[cur_arg + 1]) {
2525 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2526 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002529 }
2530
2531 cur_arg++;
2532 cookie = args[cur_arg];
2533 cookie_set = 1;
2534 }
2535 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2536 if (!*args[cur_arg + 1]) {
2537 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2538 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002539 err_code |= ERR_ALERT | ERR_FATAL;
2540 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002541 }
2542
2543 cur_arg++;
2544 cookie = args[cur_arg];
2545 cookie_set = 0;
2546 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002547 else if (!strcmp(args[cur_arg],"code")) {
2548 if (!*args[cur_arg + 1]) {
2549 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002553 }
2554 cur_arg++;
2555 code = atol(args[cur_arg]);
2556 if (code < 301 || code > 303) {
2557 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2558 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002559 err_code |= ERR_ALERT | ERR_FATAL;
2560 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002561 }
2562 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002563 else if (!strcmp(args[cur_arg],"drop-query")) {
2564 flags |= REDIRECT_FLAG_DROP_QS;
2565 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002566 else if (!strcmp(args[cur_arg],"append-slash")) {
2567 flags |= REDIRECT_FLAG_APPEND_SLASH;
2568 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002569 else if (strcmp(args[cur_arg], "if") == 0 ||
2570 strcmp(args[cur_arg], "unless") == 0) {
2571 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2572 if (!cond) {
2573 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2574 file, linenum, args[0]);
2575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
2577 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002578 break;
2579 }
2580 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002581 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 +02002582 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002585 }
2586 cur_arg++;
2587 }
2588
2589 if (type == REDIRECT_TYPE_NONE) {
2590 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2591 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002592 err_code |= ERR_ALERT | ERR_FATAL;
2593 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002594 }
2595
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002596 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2597 rule->cond = cond;
2598 rule->rdr_str = strdup(destination);
2599 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002600 if (cookie) {
2601 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002602 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002603 */
2604 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002605 if (cookie_set) {
2606 rule->cookie_str = malloc(rule->cookie_len + 10);
2607 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2608 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2609 rule->cookie_len += 9;
2610 } else {
2611 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002612 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002613 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2614 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002615 }
2616 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002617 rule->type = type;
2618 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002619 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002620 LIST_INIT(&rule->list);
2621 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002622 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2623 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002624 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002625 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002626 struct switching_rule *rule;
2627
Willy Tarreaub099aca2008-10-12 17:26:37 +02002628 if (curproxy == &defproxy) {
2629 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002632 }
2633
Willy Tarreau55ea7572007-06-17 19:56:27 +02002634 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002636
2637 if (*(args[1]) == 0) {
2638 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002641 }
2642
Willy Tarreauef6494c2010-01-28 17:12:36 +01002643 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002644 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2645 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002648 }
2649
Willy Tarreauef6494c2010-01-28 17:12:36 +01002650 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002651 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002652 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002655 }
2656
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002657 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002658
Willy Tarreau55ea7572007-06-17 19:56:27 +02002659 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2660 rule->cond = cond;
2661 rule->be.name = strdup(args[1]);
2662 LIST_INIT(&rule->list);
2663 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2664 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002665 else if ((!strcmp(args[0], "force-persist")) ||
2666 (!strcmp(args[0], "ignore-persist"))) {
2667 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002668
2669 if (curproxy == &defproxy) {
2670 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674
2675 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2676 err_code |= ERR_WARN;
2677
Willy Tarreauef6494c2010-01-28 17:12:36 +01002678 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002679 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2680 file, linenum, args[0]);
2681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684
Willy Tarreauef6494c2010-01-28 17:12:36 +01002685 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002686 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2687 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
2690 }
2691
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002692 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002693
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002694 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002695 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002696 if (!strcmp(args[0], "force-persist")) {
2697 rule->type = PERSIST_TYPE_FORCE;
2698 } else {
2699 rule->type = PERSIST_TYPE_IGNORE;
2700 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002701 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002702 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002703 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002704 else if (!strcmp(args[0], "stick-table")) {
2705 int myidx = 1;
2706
Emeric Brun32da3c42010-09-23 18:39:19 +02002707 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002708 curproxy->table.type = (unsigned int)-1;
2709 while (*args[myidx]) {
2710 const char *err;
2711
2712 if (strcmp(args[myidx], "size") == 0) {
2713 myidx++;
2714 if (!*(args[myidx])) {
2715 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2716 file, linenum, args[myidx-1]);
2717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
2719 }
2720 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2721 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2722 file, linenum, *err, args[myidx-1]);
2723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
2725 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002726 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002727 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002728 else if (strcmp(args[myidx], "peers") == 0) {
2729 myidx++;
2730 if (!*(args[myidx])) {
2731 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2732 file, linenum, args[myidx-1]);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736 curproxy->table.peers.name = strdup(args[myidx++]);
2737 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002738 else if (strcmp(args[myidx], "expire") == 0) {
2739 myidx++;
2740 if (!*(args[myidx])) {
2741 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2742 file, linenum, args[myidx-1]);
2743 err_code |= ERR_ALERT | ERR_FATAL;
2744 goto out;
2745 }
2746 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2747 if (err) {
2748 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2749 file, linenum, *err, args[myidx-1]);
2750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
2752 }
2753 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002754 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002755 }
2756 else if (strcmp(args[myidx], "nopurge") == 0) {
2757 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002758 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002759 }
2760 else if (strcmp(args[myidx], "type") == 0) {
2761 myidx++;
2762 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2763 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2764 file, linenum, args[myidx]);
2765 err_code |= ERR_ALERT | ERR_FATAL;
2766 goto out;
2767 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002768 /* myidx already points to next arg */
2769 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002770 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002771 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002772 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002773
2774 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002775 nw = args[myidx];
2776 while (*nw) {
2777 /* the "store" keyword supports a comma-separated list */
2778 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002779 sa = NULL; /* store arg */
2780 while (*nw && *nw != ',') {
2781 if (*nw == '(') {
2782 *nw = 0;
2783 sa = ++nw;
2784 while (*nw != ')') {
2785 if (!*nw) {
2786 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2787 file, linenum, args[0], cw);
2788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
2790 }
2791 nw++;
2792 }
2793 *nw = '\0';
2794 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002795 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002796 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002797 if (*nw)
2798 *nw++ = '\0';
2799 type = stktable_get_data_type(cw);
2800 if (type < 0) {
2801 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2802 file, linenum, args[0], cw);
2803 err_code |= ERR_ALERT | ERR_FATAL;
2804 goto out;
2805 }
Willy Tarreauac782882010-06-20 10:41:54 +02002806
2807 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2808 switch (err) {
2809 case PE_NONE: break;
2810 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002811 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2812 file, linenum, args[0], cw);
2813 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002814 break;
2815
2816 case PE_ARG_MISSING:
2817 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2818 file, linenum, args[0], cw);
2819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
2821
2822 case PE_ARG_NOT_USED:
2823 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2824 file, linenum, args[0], cw);
2825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
2827
2828 default:
2829 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2830 file, linenum, args[0], cw);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002833 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002834 }
2835 myidx++;
2836 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002837 else {
2838 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2839 file, linenum, args[myidx]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002842 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002843 }
2844
2845 if (!curproxy->table.size) {
2846 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2847 file, linenum);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
2851
2852 if (curproxy->table.type == (unsigned int)-1) {
2853 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2854 file, linenum);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857 }
2858 }
2859 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002860 struct sticking_rule *rule;
2861 struct pattern_expr *expr;
2862 int myidx = 0;
2863 const char *name = NULL;
2864 int flags;
2865
2866 if (curproxy == &defproxy) {
2867 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
2870 }
2871
2872 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2873 err_code |= ERR_WARN;
2874 goto out;
2875 }
2876
2877 myidx++;
2878 if ((strcmp(args[myidx], "store") == 0) ||
2879 (strcmp(args[myidx], "store-request") == 0)) {
2880 myidx++;
2881 flags = STK_IS_STORE;
2882 }
2883 else if (strcmp(args[myidx], "store-response") == 0) {
2884 myidx++;
2885 flags = STK_IS_STORE | STK_ON_RSP;
2886 }
2887 else if (strcmp(args[myidx], "match") == 0) {
2888 myidx++;
2889 flags = STK_IS_MATCH;
2890 }
2891 else if (strcmp(args[myidx], "on") == 0) {
2892 myidx++;
2893 flags = STK_IS_MATCH | STK_IS_STORE;
2894 }
2895 else {
2896 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
2899 }
2900
2901 if (*(args[myidx]) == 0) {
2902 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906
Emeric Brun485479d2010-09-23 18:02:19 +02002907 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002908 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002909 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
2912 }
2913
2914 if (flags & STK_ON_RSP) {
2915 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2916 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2917 file, linenum, args[0], expr->fetch->kw);
2918 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002919 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002920 goto out;
2921 }
2922 } else {
2923 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2924 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2925 file, linenum, args[0], expr->fetch->kw);
2926 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002927 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002928 goto out;
2929 }
2930 }
2931
2932 if (strcmp(args[myidx], "table") == 0) {
2933 myidx++;
2934 name = args[myidx++];
2935 }
2936
Willy Tarreauef6494c2010-01-28 17:12:36 +01002937 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2938 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002939 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2940 file, linenum, args[0]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002942 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 goto out;
2944 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002945 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002946 else if (*(args[myidx])) {
2947 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2948 file, linenum, args[0], args[myidx]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002950 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002951 goto out;
2952 }
Emeric Brun97679e72010-09-23 17:56:44 +02002953 if (flags & STK_ON_RSP)
2954 err_code |= warnif_cond_requires_req(cond, file, linenum);
2955 else
2956 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002957
Emeric Brunb982a3d2010-01-04 15:45:53 +01002958 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2959 rule->cond = cond;
2960 rule->expr = expr;
2961 rule->flags = flags;
2962 rule->table.name = name ? strdup(name) : NULL;
2963 LIST_INIT(&rule->list);
2964 if (flags & STK_ON_RSP)
2965 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2966 else
2967 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2974 curproxy->uri_auth = NULL; /* we must detach from the default config */
2975
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002976 if (!*args[1]) {
2977 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002978 } else if (!strcmp(args[1], "admin")) {
2979 struct stats_admin_rule *rule;
2980
2981 if (curproxy == &defproxy) {
2982 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986
2987 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2988 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2989 err_code |= ERR_ALERT | ERR_ABORT;
2990 goto out;
2991 }
2992
2993 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2994 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2995 file, linenum, args[0], args[1]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3000 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3001 file, linenum, args[0], args[1]);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
3005
3006 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3007
3008 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3009 rule->cond = cond;
3010 LIST_INIT(&rule->list);
3011 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 } else if (!strcmp(args[1], "uri")) {
3013 if (*(args[2]) == 0) {
3014 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3018 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_ABORT;
3020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 }
3022 } else if (!strcmp(args[1], "realm")) {
3023 if (*(args[2]) == 0) {
3024 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3028 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_ABORT;
3030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003032 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003033 unsigned interval;
3034
3035 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3036 if (err) {
3037 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3038 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003041 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3042 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_ABORT;
3044 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003045 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003047 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003048
3049 if (curproxy == &defproxy) {
3050 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
3053 }
3054
3055 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3056 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3057 err_code |= ERR_ALERT | ERR_ABORT;
3058 goto out;
3059 }
3060
Willy Tarreauff011f22011-01-06 17:51:27 +01003061 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3062 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003063 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3064 file, linenum, args[0]);
3065 err_code |= ERR_WARN;
3066 }
3067
Willy Tarreauff011f22011-01-06 17:51:27 +01003068 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003069
Willy Tarreauff011f22011-01-06 17:51:27 +01003070 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003071 err_code |= ERR_ALERT | ERR_ABORT;
3072 goto out;
3073 }
3074
Willy Tarreauff011f22011-01-06 17:51:27 +01003075 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3076 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003077
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 } else if (!strcmp(args[1], "auth")) {
3079 if (*(args[2]) == 0) {
3080 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3084 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_ABORT;
3086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 }
3088 } else if (!strcmp(args[1], "scope")) {
3089 if (*(args[2]) == 0) {
3090 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3094 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_ABORT;
3096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 }
3098 } else if (!strcmp(args[1], "enable")) {
3099 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3100 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_ABORT;
3102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003104 } else if (!strcmp(args[1], "hide-version")) {
3105 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3106 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003107 err_code |= ERR_ALERT | ERR_ABORT;
3108 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003109 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003110 } else if (!strcmp(args[1], "show-legends")) {
3111 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3112 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3113 err_code |= ERR_ALERT | ERR_ABORT;
3114 goto out;
3115 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003116 } else if (!strcmp(args[1], "show-node")) {
3117
3118 if (*args[2]) {
3119 int i;
3120 char c;
3121
3122 for (i=0; args[2][i]; i++) {
3123 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003124 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3125 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003126 break;
3127 }
3128
3129 if (!i || args[2][i]) {
3130 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3131 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3132 file, linenum, args[0], args[1]);
3133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
3135 }
3136 }
3137
3138 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3139 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3140 err_code |= ERR_ALERT | ERR_ABORT;
3141 goto out;
3142 }
3143 } else if (!strcmp(args[1], "show-desc")) {
3144 char *desc = NULL;
3145
3146 if (*args[2]) {
3147 int i, len=0;
3148 char *d;
3149
3150 for(i=2; *args[i]; i++)
3151 len += strlen(args[i])+1;
3152
3153 desc = d = (char *)calloc(1, len);
3154
3155 d += sprintf(d, "%s", args[2]);
3156 for(i=3; *args[i]; i++)
3157 d += sprintf(d, " %s", args[i]);
3158 }
3159
3160 if (!*args[2] && !global.desc)
3161 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3162 file, linenum, args[1]);
3163 else {
3164 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3165 free(desc);
3166 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3167 err_code |= ERR_ALERT | ERR_ABORT;
3168 goto out;
3169 }
3170 free(desc);
3171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003173stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003174 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 +01003175 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
3179 }
3180 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003181 int optnum;
3182
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003183 if (*(args[1]) == '\0') {
3184 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3185 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003189
3190 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3191 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003192 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3193 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3194 file, linenum, cfg_opts[optnum].name);
3195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
3197 }
Willy Tarreau93893792009-07-23 13:19:11 +02003198 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3199 err_code |= ERR_WARN;
3200 goto out;
3201 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003202
Willy Tarreau3842f002009-06-14 11:39:52 +02003203 curproxy->no_options &= ~cfg_opts[optnum].val;
3204 curproxy->options &= ~cfg_opts[optnum].val;
3205
3206 switch (kwm) {
3207 case KWM_STD:
3208 curproxy->options |= cfg_opts[optnum].val;
3209 break;
3210 case KWM_NO:
3211 curproxy->no_options |= cfg_opts[optnum].val;
3212 break;
3213 case KWM_DEF: /* already cleared */
3214 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003215 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003216
Willy Tarreau93893792009-07-23 13:19:11 +02003217 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003218 }
3219 }
3220
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003221 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3222 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003223 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3224 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3225 file, linenum, cfg_opts2[optnum].name);
3226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
3228 }
Willy Tarreau93893792009-07-23 13:19:11 +02003229 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3230 err_code |= ERR_WARN;
3231 goto out;
3232 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003233
Willy Tarreau3842f002009-06-14 11:39:52 +02003234 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3235 curproxy->options2 &= ~cfg_opts2[optnum].val;
3236
3237 switch (kwm) {
3238 case KWM_STD:
3239 curproxy->options2 |= cfg_opts2[optnum].val;
3240 break;
3241 case KWM_NO:
3242 curproxy->no_options2 |= cfg_opts2[optnum].val;
3243 break;
3244 case KWM_DEF: /* already cleared */
3245 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003246 }
Willy Tarreau93893792009-07-23 13:19:11 +02003247 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003248 }
3249 }
3250
Willy Tarreau3842f002009-06-14 11:39:52 +02003251 if (kwm != KWM_STD) {
3252 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003253 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003256 }
3257
Emeric Brun3a058f32009-06-30 18:26:00 +02003258 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003260 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003262 if (*(args[2]) != '\0') {
3263 if (!strcmp(args[2], "clf")) {
3264 curproxy->options2 |= PR_O2_CLFLOG;
3265 } else {
3266 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003269 }
3270 }
3271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 else if (!strcmp(args[1], "tcplog"))
3273 /* generate a detailed TCP log */
3274 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 else if (!strcmp(args[1], "tcpka")) {
3276 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003277 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003279
3280 if (curproxy->cap & PR_CAP_FE)
3281 curproxy->options |= PR_O_TCP_CLI_KA;
3282 if (curproxy->cap & PR_CAP_BE)
3283 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 }
3285 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_WARN;
3288
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003290 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003291 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003292 curproxy->options2 &= ~PR_O2_CHK_ANY;
3293 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 if (!*args[2]) { /* no argument */
3295 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3296 curproxy->check_len = strlen(DEF_CHECK_REQ);
3297 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003298 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 curproxy->check_req = (char *)malloc(reqlen);
3300 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003301 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003303 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 if (*args[4])
3305 reqlen += strlen(args[4]);
3306 else
3307 reqlen += strlen("HTTP/1.0");
3308
3309 curproxy->check_req = (char *)malloc(reqlen);
3310 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003311 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003313 }
3314 else if (!strcmp(args[1], "ssl-hello-chk")) {
3315 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003316 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003318
Willy Tarreaua534fea2008-08-03 12:19:50 +02003319 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003320 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003321 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003322 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
Willy Tarreau23677902007-05-08 23:50:35 +02003324 else if (!strcmp(args[1], "smtpchk")) {
3325 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003326 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003327 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003328 curproxy->options2 &= ~PR_O2_CHK_ANY;
3329 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003330
3331 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3332 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3333 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3334 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3335 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3336 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3337 curproxy->check_req = (char *)malloc(reqlen);
3338 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3339 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3340 } else {
3341 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3342 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3343 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3344 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3345 }
3346 }
3347 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003348 else if (!strcmp(args[1], "pgsql-check")) {
3349 /* use PostgreSQL request to check servers' health */
3350 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3351 err_code |= ERR_WARN;
3352
3353 free(curproxy->check_req);
3354 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003355 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003356 curproxy->options2 |= PR_O2_PGSQL_CHK;
3357
3358 if (*(args[2])) {
3359 int cur_arg = 2;
3360
3361 while (*(args[cur_arg])) {
3362 if (strcmp(args[cur_arg], "user") == 0) {
3363 char * packet;
3364 uint32_t packet_len;
3365 uint32_t pv;
3366
3367 /* suboption header - needs additional argument for it */
3368 if (*(args[cur_arg+1]) == 0) {
3369 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3370 file, linenum, args[0], args[1], args[cur_arg]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374
3375 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3376 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3377 pv = htonl(0x30000); /* protocol version 3.0 */
3378
3379 packet = (char*) calloc(1, packet_len);
3380
3381 memcpy(packet + 4, &pv, 4);
3382
3383 /* copy "user" */
3384 memcpy(packet + 8, "user", 4);
3385
3386 /* copy username */
3387 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3388
3389 free(curproxy->check_req);
3390 curproxy->check_req = packet;
3391 curproxy->check_len = packet_len;
3392
3393 packet_len = htonl(packet_len);
3394 memcpy(packet, &packet_len, 4);
3395 cur_arg += 2;
3396 } else {
3397 /* unknown suboption - catchall */
3398 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3399 file, linenum, args[0], args[1]);
3400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
3402 }
3403 } /* end while loop */
3404 }
3405 }
3406
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003407 else if (!strcmp(args[1], "redis-check")) {
3408 /* use REDIS PING request to check servers' health */
3409 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3410 err_code |= ERR_WARN;
3411
3412 free(curproxy->check_req);
3413 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003414 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003415 curproxy->options2 |= PR_O2_REDIS_CHK;
3416
3417 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3418 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3419 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3420 }
3421
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003422 else if (!strcmp(args[1], "mysql-check")) {
3423 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3425 err_code |= ERR_WARN;
3426
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003427 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003428 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003429 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003430 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003431
3432 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3433 * const char mysql40_client_auth_pkt[] = {
3434 * "\x0e\x00\x00" // packet length
3435 * "\x01" // packet number
3436 * "\x00\x00" // client capabilities
3437 * "\x00\x00\x01" // max packet
3438 * "haproxy\x00" // username (null terminated string)
3439 * "\x00" // filler (always 0x00)
3440 * "\x01\x00\x00" // packet length
3441 * "\x00" // packet number
3442 * "\x01" // COM_QUIT command
3443 * };
3444 */
3445
3446 if (*(args[2])) {
3447 int cur_arg = 2;
3448
3449 while (*(args[cur_arg])) {
3450 if (strcmp(args[cur_arg], "user") == 0) {
3451 char *mysqluser;
3452 int packetlen, reqlen, userlen;
3453
3454 /* suboption header - needs additional argument for it */
3455 if (*(args[cur_arg+1]) == 0) {
3456 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3457 file, linenum, args[0], args[1], args[cur_arg]);
3458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
3460 }
3461 mysqluser = args[cur_arg + 1];
3462 userlen = strlen(mysqluser);
3463 packetlen = userlen + 7;
3464 reqlen = packetlen + 9;
3465
3466 free(curproxy->check_req);
3467 curproxy->check_req = (char *)calloc(1, reqlen);
3468 curproxy->check_len = reqlen;
3469
3470 snprintf(curproxy->check_req, 4, "%c%c%c",
3471 ((unsigned char) packetlen & 0xff),
3472 ((unsigned char) (packetlen >> 8) & 0xff),
3473 ((unsigned char) (packetlen >> 16) & 0xff));
3474
3475 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003476 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003477 curproxy->check_req[8] = 1;
3478 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3479 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3480 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3481 cur_arg += 2;
3482 } else {
3483 /* unknown suboption - catchall */
3484 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3485 file, linenum, args[0], args[1]);
3486 err_code |= ERR_ALERT | ERR_FATAL;
3487 goto out;
3488 }
3489 } /* end while loop */
3490 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003491 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003492 else if (!strcmp(args[1], "ldap-check")) {
3493 /* use LDAP request to check servers' health */
3494 free(curproxy->check_req);
3495 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003496 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003497 curproxy->options2 |= PR_O2_LDAP_CHK;
3498
3499 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3500 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3501 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3502 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003503 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003504 int cur_arg;
3505
3506 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3507 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003508 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003509
Willy Tarreau87cf5142011-08-19 22:57:24 +02003510 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003511
3512 free(curproxy->fwdfor_hdr_name);
3513 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3514 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3515
3516 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3517 cur_arg = 2;
3518 while (*(args[cur_arg])) {
3519 if (!strcmp(args[cur_arg], "except")) {
3520 /* suboption except - needs additional argument for it */
3521 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3522 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3523 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_FATAL;
3525 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003526 }
3527 /* flush useless bits */
3528 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003529 cur_arg += 2;
3530 } else if (!strcmp(args[cur_arg], "header")) {
3531 /* suboption header - needs additional argument for it */
3532 if (*(args[cur_arg+1]) == 0) {
3533 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3534 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003537 }
3538 free(curproxy->fwdfor_hdr_name);
3539 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3540 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3541 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003542 } else if (!strcmp(args[cur_arg], "if-none")) {
3543 curproxy->options &= ~PR_O_FF_ALWAYS;
3544 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003545 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003546 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003547 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003548 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003549 err_code |= ERR_ALERT | ERR_FATAL;
3550 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003551 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003552 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003553 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003554 else if (!strcmp(args[1], "originalto")) {
3555 int cur_arg;
3556
3557 /* insert x-original-to field, but not for the IP address listed as an except.
3558 * set default options (ie: bitfield, header name, etc)
3559 */
3560
3561 curproxy->options |= PR_O_ORGTO;
3562
3563 free(curproxy->orgto_hdr_name);
3564 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3565 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3566
Willy Tarreau87cf5142011-08-19 22:57:24 +02003567 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003568 cur_arg = 2;
3569 while (*(args[cur_arg])) {
3570 if (!strcmp(args[cur_arg], "except")) {
3571 /* suboption except - needs additional argument for it */
3572 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3573 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3574 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003577 }
3578 /* flush useless bits */
3579 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3580 cur_arg += 2;
3581 } else if (!strcmp(args[cur_arg], "header")) {
3582 /* suboption header - needs additional argument for it */
3583 if (*(args[cur_arg+1]) == 0) {
3584 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3585 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003588 }
3589 free(curproxy->orgto_hdr_name);
3590 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3591 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3592 cur_arg += 2;
3593 } else {
3594 /* unknown suboption - catchall */
3595 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3596 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003599 }
3600 } /* end while loop */
3601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 else {
3603 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003606 }
Willy Tarreau93893792009-07-23 13:19:11 +02003607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003609 else if (!strcmp(args[0], "default_backend")) {
3610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003612
3613 if (*(args[1]) == 0) {
3614 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003617 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003618 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003619 curproxy->defbe.name = strdup(args[1]);
3620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003622 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003624
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003625 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003628 /* enable reconnections to dispatch */
3629 curproxy->options |= PR_O_REDISP;
3630 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003631 else if (!strcmp(args[0], "http-check")) {
3632 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003634
3635 if (strcmp(args[1], "disable-on-404") == 0) {
3636 /* enable a graceful server shutdown on an HTTP 404 response */
3637 curproxy->options |= PR_O_DISABLE404;
3638 }
Willy Tarreauef781042010-01-27 11:53:01 +01003639 else if (strcmp(args[1], "send-state") == 0) {
3640 /* enable emission of the apparent state of a server in HTTP checks */
3641 curproxy->options2 |= PR_O2_CHK_SNDST;
3642 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003643 else if (strcmp(args[1], "expect") == 0) {
3644 const char *ptr_arg;
3645 int cur_arg;
3646
3647 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3648 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
3651 }
3652
3653 cur_arg = 2;
3654 /* consider exclamation marks, sole or at the beginning of a word */
3655 while (*(ptr_arg = args[cur_arg])) {
3656 while (*ptr_arg == '!') {
3657 curproxy->options2 ^= PR_O2_EXP_INV;
3658 ptr_arg++;
3659 }
3660 if (*ptr_arg)
3661 break;
3662 cur_arg++;
3663 }
3664 /* now ptr_arg points to the beginning of a word past any possible
3665 * exclamation mark, and cur_arg is the argument which holds this word.
3666 */
3667 if (strcmp(ptr_arg, "status") == 0) {
3668 if (!*(args[cur_arg + 1])) {
3669 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3670 file, linenum, args[0], args[1], ptr_arg);
3671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
3673 }
3674 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003675 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003676 curproxy->expect_str = strdup(args[cur_arg + 1]);
3677 }
3678 else if (strcmp(ptr_arg, "string") == 0) {
3679 if (!*(args[cur_arg + 1])) {
3680 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3681 file, linenum, args[0], args[1], ptr_arg);
3682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
3684 }
3685 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003686 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003687 curproxy->expect_str = strdup(args[cur_arg + 1]);
3688 }
3689 else if (strcmp(ptr_arg, "rstatus") == 0) {
3690 if (!*(args[cur_arg + 1])) {
3691 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3692 file, linenum, args[0], args[1], ptr_arg);
3693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
3695 }
3696 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003697 free(curproxy->expect_str);
3698 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3699 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003700 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3701 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3702 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3703 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707 }
3708 else if (strcmp(ptr_arg, "rstring") == 0) {
3709 if (!*(args[cur_arg + 1])) {
3710 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3711 file, linenum, args[0], args[1], ptr_arg);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003716 free(curproxy->expect_str);
3717 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3718 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003719 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3720 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3721 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3722 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726 }
3727 else {
3728 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3729 file, linenum, args[0], args[1], ptr_arg);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003734 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003735 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 +02003736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003738 }
3739 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003740 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003741 if (curproxy == &defproxy) {
3742 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003743 err_code |= ERR_ALERT | ERR_FATAL;
3744 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003745 }
3746
Willy Tarreaub80c2302007-11-30 20:51:32 +01003747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003749
3750 if (strcmp(args[1], "fail") == 0) {
3751 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003752 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003753 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3754 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003757 }
3758
Willy Tarreauef6494c2010-01-28 17:12:36 +01003759 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003760 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3761 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003764 }
3765 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3766 }
3767 else {
3768 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003771 }
3772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773#ifdef TPROXY
3774 else if (!strcmp(args[0], "transparent")) {
3775 /* enable transparent proxy connections */
3776 curproxy->options |= PR_O_TRANSP;
3777 }
3778#endif
3779 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003780 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003782
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 if (*(args[1]) == 0) {
3784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003787 }
3788 curproxy->maxconn = atol(args[1]);
3789 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003790 else if (!strcmp(args[0], "backlog")) { /* backlog */
3791 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003793
3794 if (*(args[1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003798 }
3799 curproxy->backlog = atol(args[1]);
3800 }
Willy Tarreau86034312006-12-29 00:10:33 +01003801 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003804
Willy Tarreau86034312006-12-29 00:10:33 +01003805 if (*(args[1]) == 0) {
3806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003809 }
3810 curproxy->fullconn = atol(args[1]);
3811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003812 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3813 if (*(args[1]) == 0) {
3814 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003818 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3819 if (err) {
3820 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3821 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003824 }
3825 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 }
3827 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003828 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003834 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003836
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 if (strchr(args[1], ':') == NULL) {
3838 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003842 sk = str2sa(args[1]);
3843 if (!sk) {
3844 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003849 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
3851 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003854
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003855 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003856 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3857 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003861 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003862 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3864 err_code |= ERR_WARN;
3865
3866 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3867 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3868 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3869 }
3870 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3871 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3872 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3873 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003874 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3875 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3876 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3877 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003878 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003879 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003884 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003886 char *rport, *raddr;
3887 short realport = 0;
3888 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003890 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003895 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897
3898 if (!*args[2]) {
3899 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3900 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003904
3905 err = invalid_char(args[1]);
3906 if (err) {
3907 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3908 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003911 }
3912
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003913 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003914 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003915
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003916 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3917 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3918 err_code |= ERR_ALERT | ERR_ABORT;
3919 goto out;
3920 }
3921
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003922 /* the servers are linked backwards first */
3923 newsrv->next = curproxy->srv;
3924 curproxy->srv = newsrv;
3925 newsrv->proxy = curproxy;
3926 newsrv->conf.file = file;
3927 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928
Simon Hormanaf514952011-06-21 14:34:57 +09003929 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003930 LIST_INIT(&newsrv->pendconns);
3931 do_check = 0;
3932 newsrv->state = SRV_RUNNING; /* early server setup */
3933 newsrv->last_change = now.tv_sec;
3934 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003937 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003938 * - IP: => port=+0, relative
3939 * - IP:N => port=N, absolute
3940 * - IP:+N => port=+N, relative
3941 * - IP:-N => port=-N, relative
3942 */
3943 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003944 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003945 if (rport) {
3946 *rport++ = 0;
3947 realport = atol(rport);
3948 if (!isdigit((unsigned char)*rport))
3949 newsrv->state |= SRV_MAPPORTS;
3950 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003952
Willy Tarreaufab5a432011-03-04 15:31:53 +01003953 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003954 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003955 if (!sk) {
3956 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
3960 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003961 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003962
3963 newsrv->check_port = curproxy->defsrv.check_port;
3964 newsrv->inter = curproxy->defsrv.inter;
3965 newsrv->fastinter = curproxy->defsrv.fastinter;
3966 newsrv->downinter = curproxy->defsrv.downinter;
3967 newsrv->rise = curproxy->defsrv.rise;
3968 newsrv->fall = curproxy->defsrv.fall;
3969 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3970 newsrv->minconn = curproxy->defsrv.minconn;
3971 newsrv->maxconn = curproxy->defsrv.maxconn;
3972 newsrv->slowstart = curproxy->defsrv.slowstart;
3973 newsrv->onerror = curproxy->defsrv.onerror;
3974 newsrv->consecutive_errors_limit
3975 = curproxy->defsrv.consecutive_errors_limit;
3976 newsrv->uweight = newsrv->iweight
3977 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003979 newsrv->curfd = -1; /* no health-check in progress */
3980 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003982 cur_arg = 3;
3983 } else {
3984 newsrv = &curproxy->defsrv;
3985 cur_arg = 1;
3986 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003987
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003989 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003990 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003991
3992 if (!*args[cur_arg + 1]) {
3993 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3994 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003997 }
3998
3999 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004000 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004001
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004002 if (newsrv->puid <= 0) {
4003 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004004 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004007 }
4008
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004009 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4010 if (node) {
4011 struct server *target = container_of(node, struct server, conf.id);
4012 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4013 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016 }
4017 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004018 cur_arg += 2;
4019 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004020 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 newsrv->cookie = strdup(args[cur_arg + 1]);
4022 newsrv->cklen = strlen(args[cur_arg + 1]);
4023 cur_arg += 2;
4024 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004026 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4027 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4028 cur_arg += 2;
4029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004031 if (!*args[cur_arg + 1]) {
4032 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4033 file, linenum, args[cur_arg]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004039 if (newsrv->rise <= 0) {
4040 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4041 file, linenum, args[cur_arg]);
4042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
4044 }
4045
Willy Tarreau96839092010-03-29 10:02:24 +02004046 if (newsrv->health)
4047 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 cur_arg += 2;
4049 }
4050 else if (!strcmp(args[cur_arg], "fall")) {
4051 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004052
4053 if (!*args[cur_arg + 1]) {
4054 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4055 file, linenum, args[cur_arg]);
4056 err_code |= ERR_ALERT | ERR_FATAL;
4057 goto out;
4058 }
4059
4060 if (newsrv->fall <= 0) {
4061 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4062 file, linenum, args[cur_arg]);
4063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
4065 }
4066
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 cur_arg += 2;
4068 }
4069 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004070 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4071 if (err) {
4072 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4073 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004076 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004077 if (val <= 0) {
4078 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4079 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004082 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004083 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004084 cur_arg += 2;
4085 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004086 else if (!strcmp(args[cur_arg], "fastinter")) {
4087 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4088 if (err) {
4089 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4090 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004093 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004094 if (val <= 0) {
4095 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4096 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004099 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004100 newsrv->fastinter = val;
4101 cur_arg += 2;
4102 }
4103 else if (!strcmp(args[cur_arg], "downinter")) {
4104 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4105 if (err) {
4106 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4107 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004110 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004111 if (val <= 0) {
4112 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4113 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004116 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004117 newsrv->downinter = val;
4118 cur_arg += 2;
4119 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004120 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004121 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004122 if (!sk) {
4123 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4124 err_code |= ERR_ALERT | ERR_FATAL;
4125 goto out;
4126 }
4127 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004128 cur_arg += 2;
4129 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 else if (!strcmp(args[cur_arg], "port")) {
4131 newsrv->check_port = atol(args[cur_arg + 1]);
4132 cur_arg += 2;
4133 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004134 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004135 newsrv->state |= SRV_BACKUP;
4136 cur_arg ++;
4137 }
Simon Hormanfa461682011-06-25 09:39:49 +09004138 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4139 newsrv->state |= SRV_NON_STICK;
4140 cur_arg ++;
4141 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004142 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4143 newsrv->state |= SRV_SEND_PROXY;
4144 cur_arg ++;
4145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 else if (!strcmp(args[cur_arg], "weight")) {
4147 int w;
4148 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004149 if (w < 0 || w > 256) {
4150 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004155 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 cur_arg += 2;
4157 }
4158 else if (!strcmp(args[cur_arg], "minconn")) {
4159 newsrv->minconn = atol(args[cur_arg + 1]);
4160 cur_arg += 2;
4161 }
4162 else if (!strcmp(args[cur_arg], "maxconn")) {
4163 newsrv->maxconn = atol(args[cur_arg + 1]);
4164 cur_arg += 2;
4165 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004166 else if (!strcmp(args[cur_arg], "maxqueue")) {
4167 newsrv->maxqueue = atol(args[cur_arg + 1]);
4168 cur_arg += 2;
4169 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004170 else if (!strcmp(args[cur_arg], "slowstart")) {
4171 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004172 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004173 if (err) {
4174 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4175 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004178 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004179 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004180 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4181 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004184 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004185 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004186 cur_arg += 2;
4187 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004188 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004189
4190 if (!*args[cur_arg + 1]) {
4191 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4192 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004195 }
4196
4197 newsrv->trackit = strdup(args[cur_arg + 1]);
4198
4199 cur_arg += 2;
4200 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004201 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 global.maxsock++;
4203 do_check = 1;
4204 cur_arg += 1;
4205 }
Willy Tarreau96839092010-03-29 10:02:24 +02004206 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4207 newsrv->state |= SRV_MAINTAIN;
4208 newsrv->state &= ~SRV_RUNNING;
4209 newsrv->health = 0;
4210 cur_arg += 1;
4211 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004212 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004213 if (!strcmp(args[cur_arg + 1], "none"))
4214 newsrv->observe = HANA_OBS_NONE;
4215 else if (!strcmp(args[cur_arg + 1], "layer4"))
4216 newsrv->observe = HANA_OBS_LAYER4;
4217 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4218 if (curproxy->mode != PR_MODE_HTTP) {
4219 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4220 file, linenum, args[cur_arg + 1]);
4221 err_code |= ERR_ALERT;
4222 }
4223 newsrv->observe = HANA_OBS_LAYER7;
4224 }
4225 else {
4226 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004227 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004228 file, linenum, args[cur_arg], args[cur_arg + 1]);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
4231 }
4232
4233 cur_arg += 2;
4234 }
4235 else if (!strcmp(args[cur_arg], "on-error")) {
4236 if (!strcmp(args[cur_arg + 1], "fastinter"))
4237 newsrv->onerror = HANA_ONERR_FASTINTER;
4238 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4239 newsrv->onerror = HANA_ONERR_FAILCHK;
4240 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4241 newsrv->onerror = HANA_ONERR_SUDDTH;
4242 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4243 newsrv->onerror = HANA_ONERR_MARKDWN;
4244 else {
4245 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004246 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004247 file, linenum, args[cur_arg], args[cur_arg + 1]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251
4252 cur_arg += 2;
4253 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004254 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4255 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4256 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4257 else {
4258 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4259 file, linenum, args[cur_arg], args[cur_arg + 1]);
4260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263
4264 cur_arg += 2;
4265 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004266 else if (!strcmp(args[cur_arg], "error-limit")) {
4267 if (!*args[cur_arg + 1]) {
4268 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4269 file, linenum, args[cur_arg]);
4270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
4272 }
4273
4274 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4275
4276 if (newsrv->consecutive_errors_limit <= 0) {
4277 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4278 file, linenum, args[cur_arg]);
4279 err_code |= ERR_ALERT | ERR_FATAL;
4280 goto out;
4281 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004282 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004283 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004284 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004285 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004286 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004287
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004289#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004290 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004291 file, linenum, "source", "usesrc");
4292#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004293 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004295#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 }
4299 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004300 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4301 if (!sk) {
4302 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004307
4308 if (port_low != port_high) {
4309 int i;
4310 if (port_low <= 0 || port_low > 65535 ||
4311 port_high <= 0 || port_high > 65535 ||
4312 port_low > port_high) {
4313 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4314 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004317 }
4318 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4319 for (i = 0; i < newsrv->sport_range->size; i++)
4320 newsrv->sport_range->ports[i] = port_low + i;
4321 }
4322
Willy Tarreaubaaee002006-06-26 02:48:02 +02004323 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004324 while (*(args[cur_arg])) {
4325 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004326#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4327#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4329 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4330 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004333 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004334#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004335 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004336 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004337 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004338 err_code |= ERR_ALERT | ERR_FATAL;
4339 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004340 }
4341 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004342 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004343 newsrv->state |= SRV_TPROXY_CLI;
4344 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004345 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004346 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004347 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4348 char *name, *end;
4349
4350 name = args[cur_arg+1] + 7;
4351 while (isspace(*name))
4352 name++;
4353
4354 end = name;
4355 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4356 end++;
4357
4358 newsrv->state &= ~SRV_TPROXY_MASK;
4359 newsrv->state |= SRV_TPROXY_DYN;
4360 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4361 newsrv->bind_hdr_len = end - name;
4362 memcpy(newsrv->bind_hdr_name, name, end - name);
4363 newsrv->bind_hdr_name[end-name] = '\0';
4364 newsrv->bind_hdr_occ = -1;
4365
4366 /* now look for an occurrence number */
4367 while (isspace(*end))
4368 end++;
4369 if (*end == ',') {
4370 end++;
4371 name = end;
4372 if (*end == '-')
4373 end++;
4374 while (isdigit(*end))
4375 end++;
4376 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4377 }
4378
4379 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4380 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4381 " occurrences values smaller than %d.\n",
4382 file, linenum, MAX_HDR_HISTORY);
4383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
4385 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004387 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004388 if (!sk) {
4389 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004394 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395 }
4396 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004397#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004398 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004399#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004400 cur_arg += 2;
4401 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004402#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004403 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004404 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004407#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4408 } /* "usesrc" */
4409
4410 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4411#ifdef SO_BINDTODEVICE
4412 if (!*args[cur_arg + 1]) {
4413 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4414 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004417 }
4418 if (newsrv->iface_name)
4419 free(newsrv->iface_name);
4420
4421 newsrv->iface_name = strdup(args[cur_arg + 1]);
4422 newsrv->iface_len = strlen(newsrv->iface_name);
4423 global.last_checks |= LSTCHK_NETADM;
4424#else
4425 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4426 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004429#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 cur_arg += 2;
4431 continue;
4432 }
4433 /* this keyword in not an option of "source" */
4434 break;
4435 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004437 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004438 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4439 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004443 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004444 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004445 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 +01004446 file, linenum, newsrv->id);
4447 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004448 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 +01004449 file, linenum);
4450
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 }
4454 }
4455
4456 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004457 if (newsrv->trackit) {
4458 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4459 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004462 }
4463
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004464 /* try to get the port from check_addr if check_port not set */
4465 if (!newsrv->check_port)
4466 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004467
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4469 newsrv->check_port = realport; /* by default */
4470 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004471 /* not yet valid, because no port was set on
4472 * the server either. We'll check if we have
4473 * a known port on the first listener.
4474 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004475 struct listener *l = curproxy->listen;
4476 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4477 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004478 }
4479 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4481 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004485
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004486 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004487 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004488 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4489 err_code |= ERR_ALERT | ERR_ABORT;
4490 goto out;
4491 }
4492
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004493 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 newsrv->state |= SRV_CHECKED;
4495 }
4496
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004497 if (!defsrv) {
4498 if (newsrv->state & SRV_BACKUP)
4499 curproxy->srv_bck++;
4500 else
4501 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004502
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004503 newsrv->prev_state = newsrv->state;
4504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 }
4506 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004507 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 int facility;
4509
4510 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4511 curproxy->logfac1 = global.logfac1;
4512 curproxy->logsrv1 = global.logsrv1;
4513 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004514 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004515 curproxy->logfac2 = global.logfac2;
4516 curproxy->logsrv2 = global.logsrv2;
4517 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004518 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004519 }
4520 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004521 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004522
4523 facility = get_log_facility(args[2]);
4524 if (facility < 0) {
4525 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4526 exit(1);
4527 }
4528
4529 level = 7; /* max syslog level = debug */
4530 if (*(args[3])) {
4531 level = get_log_level(args[3]);
4532 if (level < 0) {
4533 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4534 exit(1);
4535 }
4536 }
4537
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004538 minlvl = 0; /* limit syslog level to this level (emerg) */
4539 if (*(args[4])) {
4540 minlvl = get_log_level(args[4]);
4541 if (level < 0) {
4542 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4543 exit(1);
4544 }
4545 }
4546
Robert Tsai81ae1952007-12-05 10:47:29 +01004547 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004548 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004549 if (!sk) {
4550 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004551 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004555 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004556 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004557 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004558 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004559 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004563 logsrv.addr = *sk;
4564 if (!get_host_port(&logsrv.addr))
4565 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004567
4568 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004569 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004570 curproxy->logfac1 = facility;
4571 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004572 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
4574 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004575 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 curproxy->logfac2 = facility;
4577 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004578 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 }
4580 else {
4581 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 }
4585 }
4586 else {
4587 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4588 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004589 err_code |= ERR_ALERT | ERR_FATAL;
4590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
4592 }
4593 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004594 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004595 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004596
Willy Tarreau977b8e42006-12-29 14:19:17 +01004597 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004599
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004601 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4602 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004606
4607 /* we must first clear any optional default setting */
4608 curproxy->options &= ~PR_O_TPXY_MASK;
4609 free(curproxy->iface_name);
4610 curproxy->iface_name = NULL;
4611 curproxy->iface_len = 0;
4612
Willy Tarreaud5191e72010-02-09 20:50:45 +01004613 sk = str2sa(args[1]);
4614 if (!sk) {
4615 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
4618 }
4619 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004621
4622 cur_arg = 2;
4623 while (*(args[cur_arg])) {
4624 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004625#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4626#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004627 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4628 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4629 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004632 }
4633#endif
4634 if (!*args[cur_arg + 1]) {
4635 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4636 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004639 }
4640
4641 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004642 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004643 curproxy->options |= PR_O_TPXY_CLI;
4644 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004645 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004646 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004647 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4648 char *name, *end;
4649
4650 name = args[cur_arg+1] + 7;
4651 while (isspace(*name))
4652 name++;
4653
4654 end = name;
4655 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4656 end++;
4657
4658 curproxy->options &= ~PR_O_TPXY_MASK;
4659 curproxy->options |= PR_O_TPXY_DYN;
4660 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4661 curproxy->bind_hdr_len = end - name;
4662 memcpy(curproxy->bind_hdr_name, name, end - name);
4663 curproxy->bind_hdr_name[end-name] = '\0';
4664 curproxy->bind_hdr_occ = -1;
4665
4666 /* now look for an occurrence number */
4667 while (isspace(*end))
4668 end++;
4669 if (*end == ',') {
4670 end++;
4671 name = end;
4672 if (*end == '-')
4673 end++;
4674 while (isdigit(*end))
4675 end++;
4676 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4677 }
4678
4679 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4680 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4681 " occurrences values smaller than %d.\n",
4682 file, linenum, MAX_HDR_HISTORY);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004686 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004687 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004688 if (!sk) {
4689 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
4692 }
4693 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004694 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004695 }
4696 global.last_checks |= LSTCHK_NETADM;
4697#if !defined(CONFIG_HAP_LINUX_TPROXY)
4698 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004699#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700#else /* no TPROXY support */
4701 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004702 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004703 err_code |= ERR_ALERT | ERR_FATAL;
4704 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004705#endif
4706 cur_arg += 2;
4707 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004708 }
4709
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004710 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4711#ifdef SO_BINDTODEVICE
4712 if (!*args[cur_arg + 1]) {
4713 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004717 }
4718 if (curproxy->iface_name)
4719 free(curproxy->iface_name);
4720
4721 curproxy->iface_name = strdup(args[cur_arg + 1]);
4722 curproxy->iface_len = strlen(curproxy->iface_name);
4723 global.last_checks |= LSTCHK_NETADM;
4724#else
4725 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4726 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004729#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004730 cur_arg += 2;
4731 continue;
4732 }
4733 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4734 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004739 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4740 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4741 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004742 err_code |= ERR_ALERT | ERR_FATAL;
4743 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004746 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752
4753 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4754 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004755 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004756 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 }
4759 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004760 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4761 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004762 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004763 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004765 }
4766 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4768 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004769 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004770 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
4773 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4775 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004776 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004777 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 }
4780 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004781 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4782 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004783 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004784 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004787 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004788 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4789 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004790 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004791 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004792 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004793 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004794 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004795 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4796 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004797 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004798 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004799 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004800 }
4801 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4803 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004804 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004805 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004806 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4811 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815
4816 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4817 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004818 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 }
4822 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4824 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004825 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 }
4829 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4831 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004832 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004833 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
4836 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4838 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004839 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
4843 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4845 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004846 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004850 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004851 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4852 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004853 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004855 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004858 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004859
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 if (curproxy == &defproxy) {
4861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004865 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 if (*(args[1]) == 0) {
4869 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004873
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004874 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4875 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4876 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4877 file, linenum, args[0]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
4881 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4882 }
4883 else if (*args[2]) {
4884 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4885 file, linenum, args[0], args[2]);
4886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
4888 }
4889
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004890 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004891 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004892 wl->s = strdup(args[1]);
4893 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004894 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895 }
4896 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004897 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4899 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004903
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4905 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004906 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 }
4910 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4912 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004913 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
4917 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4919 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004920 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
4924 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4927 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4933 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004934 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
4938 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4940 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4947 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004948 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004953 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004954
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 if (curproxy == &defproxy) {
4956 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004960 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 if (*(args[1]) == 0) {
4964 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
4968
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004969 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4970 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4971 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4972 file, linenum, args[0]);
4973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975 }
4976 err_code |= warnif_cond_requires_req(cond, file, linenum);
4977 }
4978 else if (*args[2]) {
4979 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4980 file, linenum, args[0], args[2]);
4981 err_code |= ERR_ALERT | ERR_FATAL;
4982 goto out;
4983 }
4984
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004985 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004986 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004987 wl->s = strdup(args[1]);
4988 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
4990 else if (!strcmp(args[0], "errorloc") ||
4991 !strcmp(args[0], "errorloc302") ||
4992 !strcmp(args[0], "errorloc303")) { /* error location */
4993 int errnum, errlen;
4994 char *err;
4995
Willy Tarreau977b8e42006-12-29 14:19:17 +01004996 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004997 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004998
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005000 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
5004
5005 errnum = atol(args[1]);
5006 if (!strcmp(args[0], "errorloc303")) {
5007 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5008 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5009 } else {
5010 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5011 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5012 }
5013
Willy Tarreau0f772532006-12-23 20:51:41 +01005014 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5015 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005016 chunk_destroy(&curproxy->errmsg[rc]);
5017 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005018 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005021
5022 if (rc >= HTTP_ERR_SIZE) {
5023 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5024 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 free(err);
5026 }
5027 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005028 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5029 int errnum, errlen, fd;
5030 char *err;
5031 struct stat stat;
5032
5033 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005034 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005035
5036 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005037 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005038 err_code |= ERR_ALERT | ERR_FATAL;
5039 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005040 }
5041
5042 fd = open(args[2], O_RDONLY);
5043 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5044 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5045 file, linenum, args[2], args[1]);
5046 if (fd >= 0)
5047 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005050 }
5051
Willy Tarreau27a674e2009-08-17 07:23:33 +02005052 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005053 errlen = stat.st_size;
5054 } else {
5055 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005056 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005058 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005059 }
5060
5061 err = malloc(errlen); /* malloc() must succeed during parsing */
5062 errnum = read(fd, err, errlen);
5063 if (errnum != errlen) {
5064 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5065 file, linenum, args[2], args[1]);
5066 close(fd);
5067 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_ALERT | ERR_FATAL;
5069 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005070 }
5071 close(fd);
5072
5073 errnum = atol(args[1]);
5074 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5075 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005076 chunk_destroy(&curproxy->errmsg[rc]);
5077 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005078 break;
5079 }
5080 }
5081
5082 if (rc >= HTTP_ERR_SIZE) {
5083 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5084 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005086 free(err);
5087 }
5088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005090 struct cfg_kw_list *kwl;
5091 int index;
5092
5093 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5094 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5095 if (kwl->kw[index].section != CFG_LISTEN)
5096 continue;
5097 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5098 /* prepare error message just in case */
5099 snprintf(trash, sizeof(trash),
5100 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005101 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5102 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005103 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005106 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005107 else if (rc > 0) {
5108 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_WARN;
5110 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005111 }
Willy Tarreau93893792009-07-23 13:19:11 +02005112 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005113 }
5114 }
5115 }
5116
Willy Tarreau6daf3432008-01-22 16:44:08 +01005117 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
Willy Tarreau93893792009-07-23 13:19:11 +02005121 out:
5122 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123}
5124
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005125int
5126cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5127{
5128
5129 int err_code = 0;
5130 const char *err;
5131
5132 if (!strcmp(args[0], "userlist")) { /* new userlist */
5133 struct userlist *newul;
5134
5135 if (!*args[1]) {
5136 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5137 file, linenum, args[0]);
5138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
5140 }
5141
5142 err = invalid_char(args[1]);
5143 if (err) {
5144 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5145 file, linenum, *err, args[0], args[1]);
5146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
5148 }
5149
5150 for (newul = userlist; newul; newul = newul->next)
5151 if (!strcmp(newul->name, args[1])) {
5152 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5153 file, linenum, args[1]);
5154 err_code |= ERR_WARN;
5155 goto out;
5156 }
5157
5158 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5159 if (!newul) {
5160 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5161 err_code |= ERR_ALERT | ERR_ABORT;
5162 goto out;
5163 }
5164
5165 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5166 newul->name = strdup(args[1]);
5167
5168 if (!newul->groupusers | !newul->name) {
5169 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5170 err_code |= ERR_ALERT | ERR_ABORT;
5171 goto out;
5172 }
5173
5174 newul->next = userlist;
5175 userlist = newul;
5176
5177 } else if (!strcmp(args[0], "group")) { /* new group */
5178 int cur_arg, i;
5179 const char *err;
5180
5181 if (!*args[1]) {
5182 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5183 file, linenum, args[0]);
5184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
5186 }
5187
5188 err = invalid_char(args[1]);
5189 if (err) {
5190 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5191 file, linenum, *err, args[0], args[1]);
5192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
5195
5196 for(i = 0; i < userlist->grpcnt; i++)
5197 if (!strcmp(userlist->groups[i], args[1])) {
5198 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5199 file, linenum, args[1], userlist->name);
5200 err_code |= ERR_ALERT;
5201 goto out;
5202 }
5203
5204 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5205 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5206 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
5209 }
5210
5211 cur_arg = 2;
5212
5213 while (*args[cur_arg]) {
5214 if (!strcmp(args[cur_arg], "users")) {
5215 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5216 cur_arg += 2;
5217 continue;
5218 } else {
5219 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5220 file, linenum, args[0]);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
5224 }
5225
5226 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5227 } else if (!strcmp(args[0], "user")) { /* new user */
5228 struct auth_users *newuser;
5229 int cur_arg;
5230
5231 if (!*args[1]) {
5232 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5233 file, linenum, args[0]);
5234 err_code |= ERR_ALERT | ERR_FATAL;
5235 goto out;
5236 }
5237
5238 for (newuser = userlist->users; newuser; newuser = newuser->next)
5239 if (!strcmp(newuser->user, args[1])) {
5240 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5241 file, linenum, args[1], userlist->name);
5242 err_code |= ERR_ALERT;
5243 goto out;
5244 }
5245
5246 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5247 if (!newuser) {
5248 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5249 err_code |= ERR_ALERT | ERR_ABORT;
5250 goto out;
5251 }
5252
5253 newuser->user = strdup(args[1]);
5254
5255 newuser->next = userlist->users;
5256 userlist->users = newuser;
5257
5258 cur_arg = 2;
5259
5260 while (*args[cur_arg]) {
5261 if (!strcmp(args[cur_arg], "password")) {
5262#ifndef CONFIG_HAP_CRYPT
5263 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5264 file, linenum);
5265 err_code |= ERR_ALERT;
5266#endif
5267 newuser->pass = strdup(args[cur_arg + 1]);
5268 cur_arg += 2;
5269 continue;
5270 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5271 newuser->pass = strdup(args[cur_arg + 1]);
5272 newuser->flags |= AU_O_INSECURE;
5273 cur_arg += 2;
5274 continue;
5275 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005276 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005277 cur_arg += 2;
5278 continue;
5279 } else {
5280 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5281 file, linenum, args[0]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 }
5286 } else {
5287 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5288 err_code |= ERR_ALERT | ERR_FATAL;
5289 }
5290
5291out:
5292 return err_code;
5293}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005294
5295/*
5296 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005297 * Returns the error code, 0 if OK, or any combination of :
5298 * - ERR_ABORT: must abort ASAP
5299 * - ERR_FATAL: we can continue parsing but not start the service
5300 * - ERR_WARN: a warning has been emitted
5301 * - ERR_ALERT: an alert has been emitted
5302 * Only the two first ones can stop processing, the two others are just
5303 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005305int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005307 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 FILE *f;
5309 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005311 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 if ((f=fopen(file,"r")) == NULL)
5314 return -1;
5315
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005316 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005317 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005318 char *end;
5319 char *args[MAX_LINE_ARGS + 1];
5320 char *line = thisline;
5321
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 linenum++;
5323
5324 end = line + strlen(line);
5325
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005326 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5327 /* Check if we reached the limit and the last char is not \n.
5328 * Watch out for the last line without the terminating '\n'!
5329 */
5330 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005331 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005332 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005333 }
5334
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005336 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005337 line++;
5338
5339 arg = 0;
5340 args[arg] = line;
5341
5342 while (*line && arg < MAX_LINE_ARGS) {
5343 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5344 * C equivalent value. Other combinations left unchanged (eg: \1).
5345 */
5346 if (*line == '\\') {
5347 int skip = 0;
5348 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5349 *line = line[1];
5350 skip = 1;
5351 }
5352 else if (line[1] == 'r') {
5353 *line = '\r';
5354 skip = 1;
5355 }
5356 else if (line[1] == 'n') {
5357 *line = '\n';
5358 skip = 1;
5359 }
5360 else if (line[1] == 't') {
5361 *line = '\t';
5362 skip = 1;
5363 }
5364 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005365 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 unsigned char hex1, hex2;
5367 hex1 = toupper(line[2]) - '0';
5368 hex2 = toupper(line[3]) - '0';
5369 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5370 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5371 *line = (hex1<<4) + hex2;
5372 skip = 3;
5373 }
5374 else {
5375 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005376 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
5378 }
5379 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005380 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 end -= skip;
5382 }
5383 line++;
5384 }
5385 else if (*line == '#' || *line == '\n' || *line == '\r') {
5386 /* end of string, end of loop */
5387 *line = 0;
5388 break;
5389 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005390 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005392 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005393 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 line++;
5395 args[++arg] = line;
5396 }
5397 else {
5398 line++;
5399 }
5400 }
5401
5402 /* empty line */
5403 if (!**args)
5404 continue;
5405
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005406 if (*line) {
5407 /* we had to stop due to too many args.
5408 * Let's terminate the string, print the offending part then cut the
5409 * last arg.
5410 */
5411 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5412 line++;
5413 *line = '\0';
5414
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005415 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005416 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005417 err_code |= ERR_ALERT | ERR_FATAL;
5418 args[arg] = line;
5419 }
5420
Willy Tarreau540abe42007-05-02 20:50:16 +02005421 /* zero out remaining args and ensure that at least one entry
5422 * is zeroed out.
5423 */
5424 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 args[arg] = line;
5426 }
5427
Willy Tarreau3842f002009-06-14 11:39:52 +02005428 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005429 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005430 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005431 for (arg=0; *args[arg+1]; arg++)
5432 args[arg] = args[arg+1]; // shift args after inversion
5433 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005434 else if (!strcmp(args[0], "default")) {
5435 kwm = KWM_DEF;
5436 for (arg=0; *args[arg+1]; arg++)
5437 args[arg] = args[arg+1]; // shift args after inversion
5438 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005439
Willy Tarreau3842f002009-06-14 11:39:52 +02005440 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5441 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005442 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005443 }
5444
Willy Tarreau977b8e42006-12-29 14:19:17 +01005445 if (!strcmp(args[0], "listen") ||
5446 !strcmp(args[0], "frontend") ||
5447 !strcmp(args[0], "backend") ||
5448 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005449 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005451 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005452 cursection = strdup(args[0]);
5453 }
5454 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005456 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005457 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005458 }
5459 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005460 confsect = CFG_USERLIST;
5461 free(cursection);
5462 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005463 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005464 else if (!strcmp(args[0], "peers")) {
5465 confsect = CFG_PEERS;
5466 free(cursection);
5467 cursection = strdup(args[0]);
5468 }
5469
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 /* else it's a section keyword */
5471
5472 switch (confsect) {
5473 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005474 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 break;
5476 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005477 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005479 case CFG_USERLIST:
5480 err_code |= cfg_parse_users(file, linenum, args, kwm);
5481 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005482 case CFG_PEERS:
5483 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5484 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005486 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005487 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005489
5490 if (err_code & ERR_ABORT)
5491 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005493 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005494 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005496 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005497}
5498
Willy Tarreaubb925012009-07-23 13:36:36 +02005499/*
5500 * Returns the error code, 0 if OK, or any combination of :
5501 * - ERR_ABORT: must abort ASAP
5502 * - ERR_FATAL: we can continue parsing but not start the service
5503 * - ERR_WARN: a warning has been emitted
5504 * - ERR_ALERT: an alert has been emitted
5505 * Only the two first ones can stop processing, the two others are just
5506 * indicators.
5507 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005508int check_config_validity()
5509{
5510 int cfgerr = 0;
5511 struct proxy *curproxy = NULL;
5512 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005513 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005514 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005515 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516
5517 /*
5518 * Now, check for the integrity of all that we have collected.
5519 */
5520
5521 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005522 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005524 /* first, we will invert the proxy list order */
5525 curproxy = NULL;
5526 while (proxy) {
5527 struct proxy *next;
5528
5529 next = proxy->next;
5530 proxy->next = curproxy;
5531 curproxy = proxy;
5532 if (!next)
5533 break;
5534 proxy = next;
5535 }
5536
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005538 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 }
5542
5543 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005544 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005545 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005546 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005547 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005548 unsigned int next_id;
5549
5550 if (!curproxy->uuid) {
5551 /* proxy ID not set, use automatic numbering with first
5552 * spare entry starting with next_pxid.
5553 */
5554 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5555 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5556 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005557 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005558 next_pxid++;
5559
Willy Tarreau55ea7572007-06-17 19:56:27 +02005560
Willy Tarreaubaaee002006-06-26 02:48:02 +02005561 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005562 /* ensure we don't keep listeners uselessly bound */
5563 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 curproxy = curproxy->next;
5565 continue;
5566 }
5567
Willy Tarreauff01a212009-03-15 13:46:16 +01005568 switch (curproxy->mode) {
5569 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005570 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005571 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005572 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5573 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005574 cfgerr++;
5575 }
5576
5577 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005578 Warning("config : servers will be ignored for %s '%s'.\n",
5579 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005580 break;
5581
5582 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005584 break;
5585
5586 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005587 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005588 break;
5589 }
5590
5591 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005592 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5593 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 cfgerr++;
5595 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005596
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005597 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005598 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005599 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005600 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5601 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005602 cfgerr++;
5603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005605 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005606 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5607 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005608 cfgerr++;
5609 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005611 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005612 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5613 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005614 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005615 }
5616 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005617 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 /* If no LB algo is set in a backend, and we're not in
5619 * transparent mode, dispatch mode nor proxy mode, we
5620 * want to use balance roundrobin by default.
5621 */
5622 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5623 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 }
5625 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005626
Willy Tarreau1620ec32011-08-06 17:05:02 +02005627 if (curproxy->options & PR_O_DISPATCH)
5628 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5629 else if (curproxy->options & PR_O_HTTP_PROXY)
5630 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5631 else if (curproxy->options & PR_O_TRANSP)
5632 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005633
Willy Tarreau1620ec32011-08-06 17:05:02 +02005634 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5635 if (curproxy->options & PR_O_DISABLE404) {
5636 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5637 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5638 err_code |= ERR_WARN;
5639 curproxy->options &= ~PR_O_DISABLE404;
5640 }
5641 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5642 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5643 "send-state", proxy_type_str(curproxy), curproxy->id);
5644 err_code |= ERR_WARN;
5645 curproxy->options &= ~PR_O2_CHK_SNDST;
5646 }
Willy Tarreauef781042010-01-27 11:53:01 +01005647 }
5648
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005649 /* if a default backend was specified, let's find it */
5650 if (curproxy->defbe.name) {
5651 struct proxy *target;
5652
Alex Williams96532db2009-11-01 21:27:13 -05005653 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005654 if (!target) {
5655 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5656 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005657 cfgerr++;
5658 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005659 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5660 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005661 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005662 } else {
5663 free(curproxy->defbe.name);
5664 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005665 /* we force the backend to be present on at least all of
5666 * the frontend's processes.
5667 */
5668 target->bind_proc = curproxy->bind_proc ?
5669 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 }
5671 }
5672
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005673 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005674 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5675 /* map jump target for ACT_SETBE in req_rep chain */
5676 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005677 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005678 struct proxy *target;
5679
Willy Tarreaua496b602006-12-17 23:15:24 +01005680 if (exp->action != ACT_SETBE)
5681 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005682
Alex Williams96532db2009-11-01 21:27:13 -05005683 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005684 if (!target) {
5685 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5686 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005687 cfgerr++;
5688 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005689 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5690 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005691 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005692 } else {
5693 free((void *)exp->replace);
5694 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005695 /* we force the backend to be present on at least all of
5696 * the frontend's processes.
5697 */
5698 target->bind_proc = curproxy->bind_proc ?
5699 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005700 }
5701 }
5702 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005703
5704 /* find the target proxy for 'use_backend' rules */
5705 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005706 struct proxy *target;
5707
Alex Williams96532db2009-11-01 21:27:13 -05005708 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005709
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005710 if (!target) {
5711 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5712 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005713 cfgerr++;
5714 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005715 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5716 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005717 cfgerr++;
5718 } else {
5719 free((void *)rule->be.name);
5720 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005721 /* we force the backend to be present on at least all of
5722 * the frontend's processes.
5723 */
5724 target->bind_proc = curproxy->bind_proc ?
5725 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005726 }
5727 }
5728
Emeric Brunb982a3d2010-01-04 15:45:53 +01005729 /* find the target table for 'stick' rules */
5730 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5731 struct proxy *target;
5732
Emeric Brun1d33b292010-01-04 15:47:17 +01005733 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5734 if (mrule->flags & STK_IS_STORE)
5735 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5736
Emeric Brunb982a3d2010-01-04 15:45:53 +01005737 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005738 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005739 else
5740 target = curproxy;
5741
5742 if (!target) {
5743 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5744 curproxy->id, mrule->table.name);
5745 cfgerr++;
5746 }
5747 else if (target->table.size == 0) {
5748 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5749 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5750 cfgerr++;
5751 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005752 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005753 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5754 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5755 cfgerr++;
5756 }
5757 else {
5758 free((void *)mrule->table.name);
5759 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005760 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005761 }
5762 }
5763
5764 /* find the target table for 'store response' rules */
5765 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5766 struct proxy *target;
5767
Emeric Brun1d33b292010-01-04 15:47:17 +01005768 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5769
Emeric Brunb982a3d2010-01-04 15:45:53 +01005770 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005771 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005772 else
5773 target = curproxy;
5774
5775 if (!target) {
5776 Alert("Proxy '%s': unable to find store table '%s'.\n",
5777 curproxy->id, mrule->table.name);
5778 cfgerr++;
5779 }
5780 else if (target->table.size == 0) {
5781 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5782 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5783 cfgerr++;
5784 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005785 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005786 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5787 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5788 cfgerr++;
5789 }
5790 else {
5791 free((void *)mrule->table.name);
5792 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005793 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005794 }
5795 }
5796
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005797 /* find the target table for 'tcp-request' layer 4 rules */
5798 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5799 struct proxy *target;
5800
Willy Tarreau56123282010-08-06 19:06:56 +02005801 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005802 continue;
5803
5804 if (trule->act_prm.trk_ctr.table.n)
5805 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5806 else
5807 target = curproxy;
5808
5809 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005810 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5811 curproxy->id, trule->act_prm.trk_ctr.table.n,
5812 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005813 cfgerr++;
5814 }
5815 else if (target->table.size == 0) {
5816 Alert("Proxy '%s': table '%s' used but not configured.\n",
5817 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5818 cfgerr++;
5819 }
5820 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005821 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 +02005822 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5823 cfgerr++;
5824 }
5825 else {
5826 free(trule->act_prm.trk_ctr.table.n);
5827 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005828 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005829 * to pass a list of counters to track and allocate them right here using
5830 * stktable_alloc_data_type().
5831 */
5832 }
5833 }
5834
Willy Tarreaud1f96522010-08-03 19:34:32 +02005835 /* find the target table for 'tcp-request' layer 6 rules */
5836 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5837 struct proxy *target;
5838
Willy Tarreau56123282010-08-06 19:06:56 +02005839 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005840 continue;
5841
5842 if (trule->act_prm.trk_ctr.table.n)
5843 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5844 else
5845 target = curproxy;
5846
5847 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005848 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5849 curproxy->id, trule->act_prm.trk_ctr.table.n,
5850 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005851 cfgerr++;
5852 }
5853 else if (target->table.size == 0) {
5854 Alert("Proxy '%s': table '%s' used but not configured.\n",
5855 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5856 cfgerr++;
5857 }
5858 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005859 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 +02005860 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5861 cfgerr++;
5862 }
5863 else {
5864 free(trule->act_prm.trk_ctr.table.n);
5865 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005866 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005867 * to pass a list of counters to track and allocate them right here using
5868 * stktable_alloc_data_type().
5869 */
5870 }
5871 }
5872
Emeric Brun32da3c42010-09-23 18:39:19 +02005873 if (curproxy->table.peers.name) {
5874 struct peers *curpeers = peers;
5875
5876 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5877 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5878 free((void *)curproxy->table.peers.name);
5879 curproxy->table.peers.p = peers;
5880 break;
5881 }
5882 }
5883
5884 if (!curpeers) {
5885 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5886 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005887 free((void *)curproxy->table.peers.name);
5888 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005889 cfgerr++;
5890 }
5891 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005892 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5893 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005894 free((void *)curproxy->table.peers.name);
5895 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005896 cfgerr++;
5897 }
5898 }
5899
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005900 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005901 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005902 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5903 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5904 "proxy", curproxy->id);
5905 cfgerr++;
5906 goto out_uri_auth_compat;
5907 }
5908
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005909 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005910 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005911 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005912 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005913
Willy Tarreau95fa4692010-02-01 13:05:50 +01005914 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5915 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005916
5917 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005918 uri_auth_compat_req[i++] = "realm";
5919 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5920 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005921
Willy Tarreau95fa4692010-02-01 13:05:50 +01005922 uri_auth_compat_req[i++] = "unless";
5923 uri_auth_compat_req[i++] = "{";
5924 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5925 uri_auth_compat_req[i++] = "}";
5926 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005927
Willy Tarreauff011f22011-01-06 17:51:27 +01005928 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5929 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005930 cfgerr++;
5931 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005932 }
5933
Willy Tarreauff011f22011-01-06 17:51:27 +01005934 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005935
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005936 if (curproxy->uri_auth->auth_realm) {
5937 free(curproxy->uri_auth->auth_realm);
5938 curproxy->uri_auth->auth_realm = NULL;
5939 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005940
5941 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005942 }
5943out_uri_auth_compat:
5944
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005945 cfgerr += acl_find_targets(curproxy);
5946
Willy Tarreau2738a142006-07-08 17:28:09 +02005947 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005948 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005949 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005950 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005951 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005952 " | While not properly invalid, you will certainly encounter various problems\n"
5953 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005954 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005955 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005956 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005957 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005958
Willy Tarreau1fa31262007-12-03 00:36:16 +01005959 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5960 * We must still support older configurations, so let's find out whether those
5961 * parameters have been set or must be copied from contimeouts.
5962 */
5963 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005964 if (!curproxy->timeout.tarpit ||
5965 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005966 /* tarpit timeout not set. We search in the following order:
5967 * default.tarpit, curr.connect, default.connect.
5968 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005969 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005970 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005971 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005972 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005973 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005974 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005975 }
5976 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005977 (!curproxy->timeout.queue ||
5978 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005979 /* queue timeout not set. We search in the following order:
5980 * default.queue, curr.connect, default.connect.
5981 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005982 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005983 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005984 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005985 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005986 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005987 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005988 }
5989 }
5990
Willy Tarreau1620ec32011-08-06 17:05:02 +02005991 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005992 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5993 curproxy->check_req = (char *)malloc(curproxy->check_len);
5994 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005995 }
5996
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005997 /* The small pools required for the capture lists */
5998 if (curproxy->nb_req_cap)
5999 curproxy->req_cap_pool = create_pool("ptrcap",
6000 curproxy->nb_req_cap * sizeof(char *),
6001 MEM_F_SHARED);
6002 if (curproxy->nb_rsp_cap)
6003 curproxy->rsp_cap_pool = create_pool("ptrcap",
6004 curproxy->nb_rsp_cap * sizeof(char *),
6005 MEM_F_SHARED);
6006
Willy Tarreaubaaee002006-06-26 02:48:02 +02006007 /* first, we will invert the servers list order */
6008 newsrv = NULL;
6009 while (curproxy->srv) {
6010 struct server *next;
6011
6012 next = curproxy->srv->next;
6013 curproxy->srv->next = newsrv;
6014 newsrv = curproxy->srv;
6015 if (!next)
6016 break;
6017 curproxy->srv = next;
6018 }
6019
Willy Tarreaudd701652010-05-25 23:03:02 +02006020 /* assign automatic UIDs to servers which don't have one yet */
6021 next_id = 1;
6022 newsrv = curproxy->srv;
6023 while (newsrv != NULL) {
6024 if (!newsrv->puid) {
6025 /* server ID not set, use automatic numbering with first
6026 * spare entry starting with next_svid.
6027 */
6028 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6029 newsrv->conf.id.key = newsrv->puid = next_id;
6030 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6031 }
6032 next_id++;
6033 newsrv = newsrv->next;
6034 }
6035
Willy Tarreau20697042007-11-15 23:26:18 +01006036 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006037 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006038
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006039 /* We have to initialize the server lookup mechanism depending
6040 * on what LB algorithm was choosen.
6041 */
6042
6043 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6044 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6045 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006046 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6047 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6048 init_server_map(curproxy);
6049 } else {
6050 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6051 fwrr_init_server_groups(curproxy);
6052 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006053 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006054
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006055 case BE_LB_KIND_LC:
6056 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006057 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006058 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006059
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006060 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006061 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6062 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6063 chash_init_server_tree(curproxy);
6064 } else {
6065 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6066 init_server_map(curproxy);
6067 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006068 break;
6069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006070
6071 if (curproxy->options & PR_O_LOGASAP)
6072 curproxy->to_log &= ~LW_BYTES;
6073
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006074 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6075 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6076 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6077 proxy_type_str(curproxy), curproxy->id);
6078 err_code |= ERR_WARN;
6079 }
6080
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006081 if (curproxy->mode != PR_MODE_HTTP) {
6082 int optnum;
6083
6084 if (curproxy->options & PR_O_COOK_ANY) {
6085 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6086 proxy_type_str(curproxy), curproxy->id);
6087 err_code |= ERR_WARN;
6088 }
6089
6090 if (curproxy->uri_auth) {
6091 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6092 proxy_type_str(curproxy), curproxy->id);
6093 err_code |= ERR_WARN;
6094 curproxy->uri_auth = NULL;
6095 }
6096
Willy Tarreau87cf5142011-08-19 22:57:24 +02006097 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006098 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6099 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6100 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006101 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006102 }
6103
6104 if (curproxy->options & PR_O_ORGTO) {
6105 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6106 "originalto", proxy_type_str(curproxy), curproxy->id);
6107 err_code |= ERR_WARN;
6108 curproxy->options &= ~PR_O_ORGTO;
6109 }
6110
6111 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6112 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6113 (curproxy->cap & cfg_opts[optnum].cap) &&
6114 (curproxy->options & cfg_opts[optnum].val)) {
6115 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6116 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6117 err_code |= ERR_WARN;
6118 curproxy->options &= ~cfg_opts[optnum].val;
6119 }
6120 }
6121
6122 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6123 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6124 (curproxy->cap & cfg_opts2[optnum].cap) &&
6125 (curproxy->options2 & cfg_opts2[optnum].val)) {
6126 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6127 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6128 err_code |= ERR_WARN;
6129 curproxy->options2 &= ~cfg_opts2[optnum].val;
6130 }
6131 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006132
Willy Tarreauefa5f512010-03-30 20:13:29 +02006133#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006134 if (curproxy->bind_hdr_occ) {
6135 curproxy->bind_hdr_occ = 0;
6136 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6137 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6138 err_code |= ERR_WARN;
6139 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006140#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006141 }
6142
Willy Tarreaubaaee002006-06-26 02:48:02 +02006143 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006144 * ensure that we're not cross-dressing a TCP server into HTTP.
6145 */
6146 newsrv = curproxy->srv;
6147 while (newsrv != NULL) {
6148 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006149 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6150 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006151 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006152 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006153
Willy Tarreauefa5f512010-03-30 20:13:29 +02006154#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006155 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6156 newsrv->bind_hdr_occ = 0;
6157 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6158 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6159 err_code |= ERR_WARN;
6160 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006161#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006162 newsrv = newsrv->next;
6163 }
6164
6165 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 * If this server supports a maxconn parameter, it needs a dedicated
6167 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006168 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169 */
6170 newsrv = curproxy->srv;
6171 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006172 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006173 /* Only 'minconn' was specified, or it was higher than or equal
6174 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6175 * this will avoid further useless expensive computations.
6176 */
6177 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006178 } else if (newsrv->maxconn && !newsrv->minconn) {
6179 /* minconn was not specified, so we set it to maxconn */
6180 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 }
6182
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006183 if (newsrv->trackit) {
6184 struct proxy *px;
6185 struct server *srv;
6186 char *pname, *sname;
6187
6188 pname = newsrv->trackit;
6189 sname = strrchr(pname, '/');
6190
6191 if (sname)
6192 *sname++ = '\0';
6193 else {
6194 sname = pname;
6195 pname = NULL;
6196 }
6197
6198 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006199 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006200 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006201 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6202 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006203 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006204 cfgerr++;
6205 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006206 }
6207 } else
6208 px = curproxy;
6209
6210 srv = findserver(px, sname);
6211 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006212 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6213 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006214 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006215 cfgerr++;
6216 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006217 }
6218
6219 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006220 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006221 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006222 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006223 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006224 cfgerr++;
6225 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006226 }
6227
6228 if (curproxy != px &&
6229 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006230 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006231 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006232 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006233 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006234 cfgerr++;
6235 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006236 }
6237
6238 newsrv->tracked = srv;
6239 newsrv->tracknext = srv->tracknext;
6240 srv->tracknext = newsrv;
6241
6242 free(newsrv->trackit);
6243 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006244 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 newsrv = newsrv->next;
6246 }
6247
Willy Tarreauc1a21672009-08-16 22:37:44 +02006248 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006249 curproxy->accept = frontend_accept;
6250
Willy Tarreauc1a21672009-08-16 22:37:44 +02006251 if (curproxy->tcp_req.inspect_delay ||
6252 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006253 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006254
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006255 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006256 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006257 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006258 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006259
6260 /* both TCP and HTTP must check switching rules */
6261 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6262 }
6263
6264 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006265 if (curproxy->tcp_req.inspect_delay ||
6266 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6267 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6268
Emeric Brun97679e72010-09-23 17:56:44 +02006269 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6270 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6271
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006272 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006273 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006274 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006275 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006276
6277 /* If the backend does requires RDP cookie persistence, we have to
6278 * enable the corresponding analyser.
6279 */
6280 if (curproxy->options2 & PR_O2_RDPC_PRST)
6281 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6282 }
6283
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006284 listener = NULL;
6285 while (curproxy->listen) {
6286 struct listener *next;
6287
6288 next = curproxy->listen->next;
6289 curproxy->listen->next = listener;
6290 listener = curproxy->listen;
6291
6292 if (!next)
6293 break;
6294
6295 curproxy->listen = next;
6296 }
6297
Willy Tarreaue6b98942007-10-29 01:09:36 +01006298 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006299 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006300 listener = curproxy->listen;
6301 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006302 if (!listener->luid) {
6303 /* listener ID not set, use automatic numbering with first
6304 * spare entry starting with next_luid.
6305 */
6306 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6307 listener->conf.id.key = listener->luid = next_id;
6308 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006309 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006310 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006311
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006312 /* enable separate counters */
6313 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6314 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6315 if (!listener->name) {
6316 sprintf(trash, "sock-%d", listener->luid);
6317 listener->name = strdup(trash);
6318 }
6319 }
6320
Willy Tarreaue6b98942007-10-29 01:09:36 +01006321 if (curproxy->options & PR_O_TCP_NOLING)
6322 listener->options |= LI_O_NOLINGER;
6323 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006324 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006325 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006326 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006327 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006328 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006329 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006330
Willy Tarreau8a956912010-10-15 14:27:08 +02006331 if (listener->options & LI_O_ACC_PROXY)
6332 listener->analysers |= AN_REQ_DECODE_PROXY;
6333
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006334 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6335 listener->options |= LI_O_TCP_RULES;
6336
Willy Tarreaude3041d2010-05-31 10:56:17 +02006337 if (curproxy->mon_mask.s_addr)
6338 listener->options |= LI_O_CHK_MONNET;
6339
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006340 /* smart accept mode is automatic in HTTP mode */
6341 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6342 (curproxy->mode == PR_MODE_HTTP &&
6343 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6344 listener->options |= LI_O_NOQUICKACK;
6345
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006346 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006347 listener = listener->next;
6348 }
6349
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006350 /* Check multi-process mode compatibility for the current proxy */
6351 if (global.nbproc > 1) {
6352 int nbproc = 0;
6353 if (curproxy->bind_proc) {
6354 int proc;
6355 for (proc = 0; proc < global.nbproc; proc++) {
6356 if (curproxy->bind_proc & (1 << proc)) {
6357 nbproc++;
6358 }
6359 }
6360 } else {
6361 nbproc = global.nbproc;
6362 }
6363 if (curproxy->table.peers.name) {
6364 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6365 curproxy->id);
6366 cfgerr++;
6367 }
6368 if (nbproc > 1) {
6369 if (curproxy->uri_auth) {
6370 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6371 curproxy->id);
6372 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6373 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6374 curproxy->id);
6375 }
6376 }
6377 if (curproxy->appsession_name) {
6378 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6379 curproxy->id);
6380 }
6381 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6382 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6383 curproxy->id);
6384 }
6385 }
6386 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006387
6388 /* create the task associated with the proxy */
6389 curproxy->task = task_new();
6390 if (curproxy->task) {
6391 curproxy->task->context = curproxy;
6392 curproxy->task->process = manage_proxy;
6393 /* no need to queue, it will be done automatically if some
6394 * listener gets limited.
6395 */
6396 curproxy->task->expire = TICK_ETERNITY;
6397 } else {
6398 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6399 curproxy->id);
6400 cfgerr++;
6401 }
6402
Willy Tarreaubaaee002006-06-26 02:48:02 +02006403 curproxy = curproxy->next;
6404 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006405
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006406 /* Check multi-process mode compatibility */
6407 if (global.nbproc > 1) {
6408 if (global.stats_fe) {
6409 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6410 }
6411 }
6412
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006413 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6414 struct auth_users *curuser;
6415 int g;
6416
6417 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6418 unsigned int group_mask = 0;
6419 char *group = NULL;
6420
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006421 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006422 continue;
6423
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006424 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006425
6426 for (g = 0; g < curuserlist->grpcnt; g++)
6427 if (!strcmp(curuserlist->groups[g], group))
6428 break;
6429
6430 if (g == curuserlist->grpcnt) {
6431 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6432 curuserlist->name, group, curuser->user);
6433 err_code |= ERR_ALERT | ERR_FATAL;
6434 goto out;
6435 }
6436
6437 group_mask |= (1 << g);
6438 }
6439
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006440 free(curuser->u.groups);
6441 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006442 }
6443
6444 for (g = 0; g < curuserlist->grpcnt; g++) {
6445 char *user = NULL;
6446
6447 if (!curuserlist->groupusers[g])
6448 continue;
6449
6450 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6451 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6452 if (!strcmp(curuser->user, user))
6453 break;
6454
6455 if (!curuser) {
6456 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6457 curuserlist->name, user, curuserlist->groups[g]);
6458 err_code |= ERR_ALERT | ERR_FATAL;
6459 goto out;
6460 }
6461
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006462 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006463 }
6464
6465 free(curuserlist->groupusers[g]);
6466 }
6467
6468 free(curuserlist->groupusers);
6469
6470#ifdef DEBUG_AUTH
6471 for (g = 0; g < curuserlist->grpcnt; g++) {
6472 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6473
6474 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6475 if (curuser->group_mask & (1 << g))
6476 fprintf(stderr, " %s", curuser->user);
6477 }
6478
6479 fprintf(stderr, "\n");
6480 }
6481#endif
6482
Willy Tarreaufbb78422011-06-05 15:38:35 +02006483 }
6484
6485 /* automatically compute fullconn if not set. We must not do it in the
6486 * loop above because cross-references are not yet fully resolved.
6487 */
6488 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6489 /* If <fullconn> is not set, let's set it to 10% of the sum of
6490 * the possible incoming frontend's maxconns.
6491 */
6492 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6493 struct proxy *fe;
6494 int total = 0;
6495
6496 /* sum up the number of maxconns of frontends which
6497 * reference this backend at least once or which are
6498 * the same one ('listen').
6499 */
6500 for (fe = proxy; fe; fe = fe->next) {
6501 struct switching_rule *rule;
6502 struct hdr_exp *exp;
6503 int found = 0;
6504
6505 if (!(fe->cap & PR_CAP_FE))
6506 continue;
6507
6508 if (fe == curproxy) /* we're on a "listen" instance */
6509 found = 1;
6510
6511 if (fe->defbe.be == curproxy) /* "default_backend" */
6512 found = 1;
6513
6514 /* check if a "use_backend" rule matches */
6515 if (!found) {
6516 list_for_each_entry(rule, &fe->switching_rules, list) {
6517 if (rule->be.backend == curproxy) {
6518 found = 1;
6519 break;
6520 }
6521 }
6522 }
6523
6524 /* check if a "reqsetbe" rule matches */
6525 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6526 if (exp->action == ACT_SETBE &&
6527 (struct proxy *)exp->replace == curproxy) {
6528 found = 1;
6529 break;
6530 }
6531 }
6532
6533 /* now we've checked all possible ways to reference a backend
6534 * from a frontend.
6535 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006536 if (!found)
6537 continue;
6538 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006539 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006540 /* we have the sum of the maxconns in <total>. We only
6541 * keep 10% of that sum to set the default fullconn, with
6542 * a hard minimum of 1 (to avoid a divide by zero).
6543 */
6544 curproxy->fullconn = (total + 9) / 10;
6545 if (!curproxy->fullconn)
6546 curproxy->fullconn = 1;
6547 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006548 }
6549
Willy Tarreau056f5682010-06-06 15:51:11 +02006550 /* initialize stick-tables on backend capable proxies. This must not
6551 * be done earlier because the data size may be discovered while parsing
6552 * other proxies.
6553 */
6554 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006555 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006556
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006557 /*
6558 * Recount currently required checks.
6559 */
6560
6561 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6562 int optnum;
6563
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006564 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6565 if (curproxy->options & cfg_opts[optnum].val)
6566 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006567
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006568 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6569 if (curproxy->options2 & cfg_opts2[optnum].val)
6570 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006571 }
6572
Willy Tarreau122541c2011-09-07 21:24:49 +02006573 if (peers) {
6574 struct peers *curpeers = peers, **last;
6575 struct peer *p, *pb;
6576
6577 /* Remove all peers sections which don't have a valid listener.
6578 * This can happen when a peers section is never referenced and
6579 * does not contain a local peer.
6580 */
6581 last = &peers;
6582 while (*last) {
6583 curpeers = *last;
6584 if (curpeers->peers_fe) {
6585 last = &curpeers->next;
6586 continue;
6587 }
6588
6589 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6590 curpeers->id, localpeer);
6591
6592 p = curpeers->remote;
6593 while (p) {
6594 pb = p->next;
6595 free(p->id);
6596 free(p);
6597 p = pb;
6598 }
6599
6600 /* Destroy and unlink this curpeers section.
6601 * Note: curpeers is backed up into *last.
6602 */
6603 free(curpeers->id);
6604 curpeers = curpeers->next;
6605 free(*last);
6606 *last = curpeers;
6607 }
6608 }
6609
Willy Tarreauac1932d2011-10-24 19:14:41 +02006610 if (!global.tune.max_http_hdr)
6611 global.tune.max_http_hdr = MAX_HTTP_HDR;
6612
Willy Tarreau34eb6712011-10-24 18:15:04 +02006613 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006614 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006615 MEM_F_SHARED);
6616
Willy Tarreaubb925012009-07-23 13:36:36 +02006617 if (cfgerr > 0)
6618 err_code |= ERR_ALERT | ERR_FATAL;
6619 out:
6620 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006621}
6622
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006623/*
6624 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6625 * parsing sessions.
6626 */
6627void cfg_register_keywords(struct cfg_kw_list *kwl)
6628{
6629 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6630}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006631
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006632/*
6633 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6634 */
6635void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6636{
6637 LIST_DEL(&kwl->list);
6638 LIST_INIT(&kwl->list);
6639}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006640
6641/*
6642 * Local variables:
6643 * c-indent-level: 8
6644 * c-basic-offset: 8
6645 * End:
6646 */