blob: bf2eb36c4f5e6111d3fbe4446ebf66be757f7ad3 [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 }
William Lallemand0f99e342011-10-12 17:50:54 +0200894 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
895 /* delete previous herited or defined syslog servers */
896 struct logsrv *back;
897 struct logsrv *tmp;
898
899 if (*(args[1]) != 0) {
900 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
906 LIST_DEL(&tmp->list);
907 free(tmp);
908 }
909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200911 struct logsrv *logsrv;
912
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 if (*(args[1]) == 0 || *(args[2]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
William Lallemand0f99e342011-10-12 17:50:54 +0200918
919 logsrv = calloc(1, sizeof(struct logsrv));
920
921 logsrv->facility = get_log_facility(args[2]);
922 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200925 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927
William Lallemand0f99e342011-10-12 17:50:54 +0200928 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200930 logsrv->level = get_log_level(args[3]);
931 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200934 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 }
937
William Lallemand0f99e342011-10-12 17:50:54 +0200938 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200939 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200940 logsrv->minlvl = get_log_level(args[4]);
941 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200942 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200944 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 }
946 }
947
Robert Tsai81ae1952007-12-05 10:47:29 +0100948 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100949 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100950 if (!sk) {
951 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100952 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100953 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200954 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100955 goto out;
956 }
William Lallemand0f99e342011-10-12 17:50:54 +0200957 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100958 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100959 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100960 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
962 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200963 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100964 goto out;
965 }
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->addr = *sk;
967 if (!get_host_port(&logsrv->addr))
968 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970
William Lallemand0f99e342011-10-12 17:50:54 +0200971 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200972 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100973 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
974 char *name;
975 int len;
976
977 if (global.log_send_hostname != NULL) {
978 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT;
980 goto out;
981 }
982
983 if (*(args[1]))
984 name = args[1];
985 else
986 name = hostname;
987
988 len = strlen(name);
989
990 /* We'll add a space after the name to respect the log format */
991 free(global.log_send_hostname);
992 global.log_send_hostname = malloc(len + 2);
993 snprintf(global.log_send_hostname, len + 2, "%s ", name);
994 }
Kevinm48936af2010-12-22 16:08:21 +0000995 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
996 if (*(args[1]) == 0) {
997 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 free(global.log_tag);
1002 global.log_tag = strdup(args[1]);
1003 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001004 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1005 if (global.spread_checks != 0) {
1006 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_ALERT;
1008 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001009 }
1010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001014 }
1015 global.spread_checks = atol(args[1]);
1016 if (global.spread_checks < 0 || global.spread_checks > 50) {
1017 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001022 struct cfg_kw_list *kwl;
1023 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001024 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001025
1026 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1027 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1028 if (kwl->kw[index].section != CFG_GLOBAL)
1029 continue;
1030 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1031 /* prepare error message just in case */
1032 snprintf(trash, sizeof(trash),
1033 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001034 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1035 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001036 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001038 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001039 else if (rc > 0) {
1040 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_WARN;
1042 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001043 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001045 }
1046 }
1047 }
1048
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001052
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 out:
1054 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055}
1056
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001057void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001059 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 defproxy.mode = PR_MODE_TCP;
1061 defproxy.state = PR_STNEW;
1062 defproxy.maxconn = cfg_maxpconn;
1063 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001064
1065 defproxy.defsrv.inter = DEF_CHKINTR;
1066 defproxy.defsrv.fastinter = 0;
1067 defproxy.defsrv.downinter = 0;
1068 defproxy.defsrv.rise = DEF_RISETIME;
1069 defproxy.defsrv.fall = DEF_FALLTIME;
1070 defproxy.defsrv.check_port = 0;
1071 defproxy.defsrv.maxqueue = 0;
1072 defproxy.defsrv.minconn = 0;
1073 defproxy.defsrv.maxconn = 0;
1074 defproxy.defsrv.slowstart = 0;
1075 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1076 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1077 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078}
1079
Willy Tarreauade5ec42010-01-28 19:33:49 +01001080
1081static int create_cond_regex_rule(const char *file, int line,
1082 struct proxy *px, int dir, int action, int flags,
1083 const char *cmd, const char *reg, const char *repl,
1084 const char **cond_start)
1085{
1086 regex_t *preg = NULL;
1087 const char *err;
1088 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001089 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001090
1091 if (px == &defproxy) {
1092 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto err;
1095 }
1096
1097 if (*reg == 0) {
1098 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto err;
1101 }
1102
1103 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1104 err_code |= ERR_WARN;
1105
Willy Tarreau5321c422010-01-28 20:35:13 +01001106 if (cond_start &&
1107 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1108 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1109 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1110 file, line, cmd);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto err;
1113 }
1114 }
1115 else if (cond_start && **cond_start) {
1116 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1117 file, line, cmd, *cond_start);
1118 err_code |= ERR_ALERT | ERR_FATAL;
1119 goto err;
1120 }
1121
1122 if (dir == ACL_DIR_REQ)
1123 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001124 else
1125 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001126
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127 preg = calloc(1, sizeof(regex_t));
1128 if (!preg) {
1129 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1130 err_code = ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1135 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1136 err_code = ERR_ALERT | ERR_FATAL;
1137 goto err;
1138 }
1139
1140 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001141 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001142 if (repl && err) {
1143 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1144 file, line, cmd, *err);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto err;
1147 }
1148
1149 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1150 err_code |= ERR_WARN;
1151
1152 return err_code;
1153 err:
1154 free(preg);
1155 return err_code;
1156}
1157
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001159 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001160 * Returns the error code, 0 if OK, or any combination of :
1161 * - ERR_ABORT: must abort ASAP
1162 * - ERR_FATAL: we can continue parsing but not start the service
1163 * - ERR_WARN: a warning has been emitted
1164 * - ERR_ALERT: an alert has been emitted
1165 * Only the two first ones can stop processing, the two others are just
1166 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001168int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1169{
1170 static struct peers *curpeers = NULL;
1171 struct peer *newpeer = NULL;
1172 const char *err;
1173 int err_code = 0;
1174
1175 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1176
1177 err = invalid_char(args[1]);
1178 if (err) {
1179 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1180 file, linenum, *err, args[0], args[1]);
1181 err_code |= ERR_ALERT | ERR_FATAL;
1182 }
1183
1184 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1185 /*
1186 * If there are two proxies with the same name only following
1187 * combinations are allowed:
1188 */
1189 if (strcmp(curpeers->id, args[1]) == 0) {
1190 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1191 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1192 err_code |= ERR_WARN;
1193 }
1194 }
1195
1196 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1198 err_code |= ERR_ALERT | ERR_ABORT;
1199 goto out;
1200 }
1201
1202 curpeers->next = peers;
1203 peers = curpeers;
1204 curpeers->conf.file = file;
1205 curpeers->conf.line = linenum;
1206 curpeers->last_change = now.tv_sec;
1207 curpeers->id = strdup(args[1]);
1208 }
1209 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1210 char *rport, *raddr;
1211 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001212 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001213
1214 if (!*args[2]) {
1215 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1216 file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220
1221 err = invalid_char(args[1]);
1222 if (err) {
1223 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1224 file, linenum, *err, args[1]);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228
1229 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1230 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1231 err_code |= ERR_ALERT | ERR_ABORT;
1232 goto out;
1233 }
1234
1235 /* the peers are linked backwards first */
1236 curpeers->count++;
1237 newpeer->next = curpeers->remote;
1238 curpeers->remote = newpeer;
1239 newpeer->peers = curpeers;
1240 newpeer->conf.file = file;
1241 newpeer->conf.line = linenum;
1242
1243 newpeer->last_change = now.tv_sec;
1244 newpeer->id = strdup(args[1]);
1245
1246 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001247 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001248 if (rport) {
1249 *rport++ = 0;
1250 realport = atol(rport);
1251 }
1252 if (!realport) {
1253 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257
Willy Tarreaufab5a432011-03-04 15:31:53 +01001258 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001259 free(raddr);
1260 if (!sk) {
1261 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
1264 }
1265 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001266 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001267
1268 if (strcmp(newpeer->id, localpeer) == 0) {
1269 /* Current is local peer, it define a frontend */
1270 newpeer->local = 1;
1271
1272 if (!curpeers->peers_fe) {
1273 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1275 err_code |= ERR_ALERT | ERR_ABORT;
1276 goto out;
1277 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001278
Willy Tarreau237250c2011-07-29 01:49:03 +02001279 init_new_proxy(curpeers->peers_fe);
1280 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001281
1282 curpeers->peers_fe->last_change = now.tv_sec;
1283 curpeers->peers_fe->id = strdup(args[1]);
1284 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001285 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001286 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1287 curpeers->peers_fe->timeout.connect = 5000;
1288 curpeers->peers_fe->accept = peer_accept;
1289 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001290 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001291 err_code |= ERR_FATAL;
1292 goto out;
1293 }
1294 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1295 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1296 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1297 curpeers->peers_fe->listen->accept = session_accept;
1298 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1299 curpeers->peers_fe->listen->handler = process_session;
1300 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001301 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1302 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001303 }
1304 }
1305 } /* neither "peer" nor "peers" */
1306 else if (*args[0] != 0) {
1307 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
1310 }
1311
1312out:
1313 return err_code;
1314}
1315
1316
Willy Tarreau3842f002009-06-14 11:39:52 +02001317int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
1319 static struct proxy *curproxy = NULL;
1320 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001321 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001322 int rc;
1323 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001324 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001325 struct acl_cond *cond = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02001326 struct logsrv *tmp;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327
Willy Tarreau977b8e42006-12-29 14:19:17 +01001328 if (!strcmp(args[0], "listen"))
1329 rc = PR_CAP_LISTEN;
1330 else if (!strcmp(args[0], "frontend"))
1331 rc = PR_CAP_FE | PR_CAP_RS;
1332 else if (!strcmp(args[0], "backend"))
1333 rc = PR_CAP_BE | PR_CAP_RS;
1334 else if (!strcmp(args[0], "ruleset"))
1335 rc = PR_CAP_RS;
1336 else
1337 rc = PR_CAP_NONE;
1338
1339 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 if (!*args[1]) {
1341 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1342 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1343 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001344 err_code |= ERR_ALERT | ERR_ABORT;
1345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001347
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001348 err = invalid_char(args[1]);
1349 if (err) {
1350 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1351 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001352 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001353 }
1354
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001355 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1356 /*
1357 * If there are two proxies with the same name only following
1358 * combinations are allowed:
1359 *
1360 * listen backend frontend ruleset
1361 * listen - - - -
1362 * backend - - OK -
1363 * frontend - OK - -
1364 * ruleset - - - -
1365 */
1366
1367 if (!strcmp(curproxy->id, args[1]) &&
1368 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1369 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001370 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1371 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1372 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001373 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001374 }
1375 }
1376
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1378 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001379 err_code |= ERR_ALERT | ERR_ABORT;
1380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001382
Willy Tarreau97cb7802010-01-03 20:23:58 +01001383 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 curproxy->next = proxy;
1385 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001386 curproxy->conf.file = file;
1387 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001388 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001390 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391
1392 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001393 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001394 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001395 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001396 err_code |= ERR_FATAL;
1397 goto out;
1398 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001399 new = curproxy->listen;
1400 while (new != last) {
1401 new->conf.file = file;
1402 new->conf.line = linenum;
1403 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001404 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 }
1407
1408 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001409 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001410 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001411
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001414 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001415 curproxy->no_options = defproxy.no_options;
1416 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001417 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001418 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001419 curproxy->except_net = defproxy.except_net;
1420 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001421 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001422 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001424 if (defproxy.fwdfor_hdr_len) {
1425 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1426 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1427 }
1428
Willy Tarreaub86db342009-11-30 11:50:16 +01001429 if (defproxy.orgto_hdr_len) {
1430 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1431 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1432 }
1433
Willy Tarreau977b8e42006-12-29 14:19:17 +01001434 if (curproxy->cap & PR_CAP_FE) {
1435 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001436 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001437 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001438
1439 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001440 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1441 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001442
1443 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445
Willy Tarreau977b8e42006-12-29 14:19:17 +01001446 if (curproxy->cap & PR_CAP_BE) {
1447 curproxy->fullconn = defproxy.fullconn;
1448 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001449
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001450 if (defproxy.check_req) {
1451 curproxy->check_req = calloc(1, defproxy.check_len);
1452 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1453 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001454 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001456 if (defproxy.expect_str) {
1457 curproxy->expect_str = strdup(defproxy.expect_str);
1458 if (defproxy.expect_regex) {
1459 /* note: this regex is known to be valid */
1460 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1461 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1462 }
1463 }
1464
Willy Tarreau977b8e42006-12-29 14:19:17 +01001465 if (defproxy.cookie_name)
1466 curproxy->cookie_name = strdup(defproxy.cookie_name);
1467 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001468 if (defproxy.cookie_domain)
1469 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001470
Willy Tarreau31936852010-10-06 16:59:56 +02001471 if (defproxy.cookie_maxidle)
1472 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1473
1474 if (defproxy.cookie_maxlife)
1475 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1476
Emeric Brun647caf12009-06-30 17:57:00 +02001477 if (defproxy.rdp_cookie_name)
1478 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1479 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1480
Willy Tarreau01732802007-11-01 22:48:15 +01001481 if (defproxy.url_param_name)
1482 curproxy->url_param_name = strdup(defproxy.url_param_name);
1483 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001484
Benoitaffb4812009-03-25 13:02:10 +01001485 if (defproxy.hh_name)
1486 curproxy->hh_name = strdup(defproxy.hh_name);
1487 curproxy->hh_len = defproxy.hh_len;
1488 curproxy->hh_match_domain = defproxy.hh_match_domain;
1489
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001490 if (defproxy.iface_name)
1491 curproxy->iface_name = strdup(defproxy.iface_name);
1492 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001494
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001495 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001496 if (defproxy.capture_name)
1497 curproxy->capture_name = strdup(defproxy.capture_name);
1498 curproxy->capture_namelen = defproxy.capture_namelen;
1499 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001503 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001504 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001505 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001506 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001507 curproxy->uri_auth = defproxy.uri_auth;
1508 curproxy->mon_net = defproxy.mon_net;
1509 curproxy->mon_mask = defproxy.mon_mask;
1510 if (defproxy.monitor_uri)
1511 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1512 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001513 if (defproxy.defbe.name)
1514 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001515 }
1516
1517 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001518 curproxy->timeout.connect = defproxy.timeout.connect;
1519 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001520 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001521 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001522 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001523 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001524 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 curproxy->source_addr = defproxy.source_addr;
1526 }
1527
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001529
1530 /* copy default logsrvs to curproxy */
1531 list_for_each_entry(tmp, &defproxy.logsrvs, list) {
1532 struct logsrv *node = malloc(sizeof(struct logsrv));
1533 memcpy(node, tmp, sizeof(struct logsrv));
1534 LIST_INIT(&node->list);
1535 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1536 }
1537
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001539 curproxy->conf.used_listener_id = EB_ROOT;
1540 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001541
Willy Tarreau93893792009-07-23 13:19:11 +02001542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 }
1544 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1545 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001546 /* FIXME-20070101: we should do this too at the end of the
1547 * config parsing to free all default values.
1548 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001549 free(defproxy.check_req);
1550 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001551 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001552 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001553 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001554 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001555 free(defproxy.capture_name);
1556 free(defproxy.monitor_uri);
1557 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001558 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001559 free(defproxy.fwdfor_hdr_name);
1560 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001561 free(defproxy.orgto_hdr_name);
1562 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001563 free(defproxy.expect_str);
1564 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001565
Willy Tarreaua534fea2008-08-03 12:19:50 +02001566 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001567 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001568
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 /* we cannot free uri_auth because it might already be used */
1570 init_default_instance();
1571 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001572 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 }
1575 else if (curproxy == NULL) {
1576 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001577 err_code |= ERR_ALERT | ERR_FATAL;
1578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 }
1580
Willy Tarreau977b8e42006-12-29 14:19:17 +01001581
1582 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001584 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001585 int cur_arg;
1586
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 if (curproxy == &defproxy) {
1588 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001589 err_code |= ERR_ALERT | ERR_FATAL;
1590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001592 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594
Emeric Bruned760922010-10-22 17:59:25 +02001595 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001596 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001598 err_code |= ERR_ALERT | ERR_FATAL;
1599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001601
1602 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001603
1604 /* NOTE: the following line might create several listeners if there
1605 * are comma-separated IPs or port ranges. So all further processing
1606 * will have to be applied to all listeners created after last_listen.
1607 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001608 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001609 err_code |= ERR_ALERT | ERR_FATAL;
1610 goto out;
1611 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001612
Willy Tarreau90a570f2009-10-04 20:54:54 +02001613 new_listen = curproxy->listen;
1614 while (new_listen != last_listen) {
1615 new_listen->conf.file = file;
1616 new_listen->conf.line = linenum;
1617 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001618 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001619 }
1620
Emeric Bruned760922010-10-22 17:59:25 +02001621 /* Set default global rights and owner for unix bind */
1622 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1623 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1624 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001625 cur_arg = 2;
1626 while (*(args[cur_arg])) {
1627 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1628#ifdef SO_BINDTODEVICE
1629 struct listener *l;
1630
Emeric Bruned760922010-10-22 17:59:25 +02001631 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1632 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1633 file, linenum, args[0], args[cur_arg]);
1634 err_code |= ERR_ALERT | ERR_FATAL;
1635 goto out;
1636 }
1637
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001638 if (!*args[cur_arg + 1]) {
1639 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1640 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001643 }
1644
1645 for (l = curproxy->listen; l != last_listen; l = l->next)
1646 l->interface = strdup(args[cur_arg + 1]);
1647
1648 global.last_checks |= LSTCHK_NETADM;
1649
1650 cur_arg += 2;
1651 continue;
1652#else
1653 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1654 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001655 err_code |= ERR_ALERT | ERR_FATAL;
1656 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001657#endif
1658 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001659 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1660#ifdef TCP_MAXSEG
1661 struct listener *l;
1662 int mss;
1663
Emeric Bruned760922010-10-22 17:59:25 +02001664 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1665 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1666 file, linenum, args[0], args[cur_arg]);
1667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
1669 }
1670
Willy Tarreaube1b9182009-06-14 18:48:19 +02001671 if (!*args[cur_arg + 1]) {
1672 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1673 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001676 }
1677
Willy Tarreau48a7e722010-12-24 15:26:39 +01001678 mss = atoi(args[cur_arg + 1]);
1679 if (!mss || abs(mss) > 65535) {
1680 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001681 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001682 err_code |= ERR_ALERT | ERR_FATAL;
1683 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001684 }
1685
1686 for (l = curproxy->listen; l != last_listen; l = l->next)
1687 l->maxseg = mss;
1688
1689 cur_arg += 2;
1690 continue;
1691#else
1692 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1693 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001696#endif
1697 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001698
1699 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1700#ifdef TCP_DEFER_ACCEPT
1701 struct listener *l;
1702
1703 for (l = curproxy->listen; l != last_listen; l = l->next)
1704 l->options |= LI_O_DEF_ACCEPT;
1705
1706 cur_arg ++;
1707 continue;
1708#else
1709 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1710 file, linenum, args[0], args[cur_arg]);
1711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
1713#endif
1714 }
1715
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001716 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001717#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001718 struct listener *l;
1719
Emeric Bruned760922010-10-22 17:59:25 +02001720 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1721 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1722 file, linenum, args[0], args[cur_arg]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001727 for (l = curproxy->listen; l != last_listen; l = l->next)
1728 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001729
1730 cur_arg ++;
1731 continue;
1732#else
1733 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1734 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
1736 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001737#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001738 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001739
Willy Tarreau8a956912010-10-15 14:27:08 +02001740 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1741 struct listener *l;
1742
1743 for (l = curproxy->listen; l != last_listen; l = l->next)
1744 l->options |= LI_O_ACC_PROXY;
1745
1746 cur_arg ++;
1747 continue;
1748 }
1749
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001750 if (!strcmp(args[cur_arg], "name")) {
1751 struct listener *l;
1752
1753 for (l = curproxy->listen; l != last_listen; l = l->next)
1754 l->name = strdup(args[cur_arg + 1]);
1755
1756 cur_arg += 2;
1757 continue;
1758 }
1759
1760 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001761 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001762 struct listener *l;
1763
1764 if (curproxy->listen->next != last_listen) {
1765 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1766 file, linenum, args[cur_arg]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
1771 if (!*args[cur_arg + 1]) {
1772 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1773 file, linenum, args[cur_arg]);
1774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
1776 }
1777
1778 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001779 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001780
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001781 if (curproxy->listen->luid <= 0) {
1782 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001783 file, linenum);
1784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
1786 }
1787
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001788 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1789 if (node) {
1790 l = container_of(node, struct listener, conf.id);
1791 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1792 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1797
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001798 cur_arg += 2;
1799 continue;
1800 }
1801
Emeric Bruned760922010-10-22 17:59:25 +02001802 if (!strcmp(args[cur_arg], "mode")) {
1803
1804 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1805 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1806 file, linenum, args[0], args[cur_arg]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
1810
1811 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1812
1813 cur_arg += 2;
1814 continue;
1815 }
1816
1817 if (!strcmp(args[cur_arg], "uid")) {
1818
1819 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1820 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1821 file, linenum, args[0], args[cur_arg]);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825
1826 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1827 cur_arg += 2;
1828 continue;
1829 }
1830
1831 if (!strcmp(args[cur_arg], "gid")) {
1832
1833 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1834 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1835 file, linenum, args[0], args[cur_arg]);
1836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
1838 }
1839
1840 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1841 cur_arg += 2;
1842 continue;
1843 }
1844
1845 if (!strcmp(args[cur_arg], "user")) {
1846 struct passwd *user;
1847
1848 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1849 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1850 file, linenum, args[0], args[cur_arg]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854 user = getpwnam(args[cur_arg + 1]);
1855 if (!user) {
1856 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1857 file, linenum, args[0], args[cur_arg + 1 ]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861
1862 curproxy->listen->perm.ux.uid = user->pw_uid;
1863 cur_arg += 2;
1864 continue;
1865 }
1866
1867 if (!strcmp(args[cur_arg], "group")) {
1868 struct group *group;
1869
1870 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1871 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1872 file, linenum, args[0], args[cur_arg]);
1873 err_code |= ERR_ALERT | ERR_FATAL;
1874 goto out;
1875 }
1876 group = getgrnam(args[cur_arg + 1]);
1877 if (!group) {
1878 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1879 file, linenum, args[0], args[cur_arg + 1 ]);
1880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
1882 }
1883
1884 curproxy->listen->perm.ux.gid = group->gr_gid;
1885 cur_arg += 2;
1886 continue;
1887 }
1888
Willy Tarreaub48f9582011-09-05 01:17:06 +02001889 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 +01001890 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001891 err_code |= ERR_ALERT | ERR_FATAL;
1892 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001893 }
Willy Tarreau93893792009-07-23 13:19:11 +02001894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 }
1896 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1897 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1898 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1899 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001900 err_code |= ERR_ALERT | ERR_FATAL;
1901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001904 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001905
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906 /* flush useless bits */
1907 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001910 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001912 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001913
Willy Tarreau1c47f852006-07-09 08:22:27 +02001914 if (!*args[1]) {
1915 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001917 err_code |= ERR_ALERT | ERR_FATAL;
1918 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001919 }
1920
Willy Tarreaua534fea2008-08-03 12:19:50 +02001921 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001922 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001923 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001924 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001925 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1926
Willy Tarreau93893792009-07-23 13:19:11 +02001927 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001928 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001929 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1930 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1931 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1932 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1933 else {
1934 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001937 }
1938 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001939 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001940 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001941
1942 if (curproxy == &defproxy) {
1943 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1944 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001945 err_code |= ERR_ALERT | ERR_FATAL;
1946 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001947 }
1948
1949 if (!*args[1]) {
1950 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1951 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001954 }
1955
1956 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001957 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001958
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001959 if (curproxy->uuid <= 0) {
1960 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001961 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_ALERT | ERR_FATAL;
1963 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001964 }
1965
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001966 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1967 if (node) {
1968 struct proxy *target = container_of(node, struct proxy, conf.id);
1969 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1970 file, linenum, proxy_type_str(curproxy), curproxy->id,
1971 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1972 err_code |= ERR_ALERT | ERR_FATAL;
1973 goto out;
1974 }
1975 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001976 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001977 else if (!strcmp(args[0], "description")) {
1978 int i, len=0;
1979 char *d;
1980
Cyril Bonté99ed3272010-01-24 23:29:44 +01001981 if (curproxy == &defproxy) {
1982 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1983 file, linenum, args[0]);
1984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
1986 }
1987
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001988 if (!*args[1]) {
1989 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1990 file, linenum, args[0]);
1991 return -1;
1992 }
1993
1994 for(i=1; *args[i]; i++)
1995 len += strlen(args[i])+1;
1996
1997 d = (char *)calloc(1, len);
1998 curproxy->desc = d;
1999
2000 d += sprintf(d, "%s", args[1]);
2001 for(i=2; *args[i]; i++)
2002 d += sprintf(d, " %s", args[i]);
2003
2004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2006 curproxy->state = PR_STSTOPPED;
2007 }
2008 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2009 curproxy->state = PR_STNEW;
2010 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002011 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2012 int cur_arg = 1;
2013 unsigned int set = 0;
2014
2015 while (*args[cur_arg]) {
2016 int u;
2017 if (strcmp(args[cur_arg], "all") == 0) {
2018 set = 0;
2019 break;
2020 }
2021 else if (strcmp(args[cur_arg], "odd") == 0) {
2022 set |= 0x55555555;
2023 }
2024 else if (strcmp(args[cur_arg], "even") == 0) {
2025 set |= 0xAAAAAAAA;
2026 }
2027 else {
2028 u = str2uic(args[cur_arg]);
2029 if (u < 1 || u > 32) {
2030 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2031 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002032 err_code |= ERR_ALERT | ERR_FATAL;
2033 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002034 }
2035 if (u > global.nbproc) {
2036 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2037 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002038 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002039 }
2040 set |= 1 << (u - 1);
2041 }
2042 cur_arg++;
2043 }
2044 curproxy->bind_proc = set;
2045 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002046 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002047 if (curproxy == &defproxy) {
2048 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002051 }
2052
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002053 err = invalid_char(args[1]);
2054 if (err) {
2055 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2056 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002058 }
2059
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002060 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2061 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2062 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002063 err_code |= ERR_ALERT | ERR_FATAL;
2064 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002065 }
2066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2068 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069
Willy Tarreau977b8e42006-12-29 14:19:17 +01002070 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002072
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 if (*(args[1]) == 0) {
2074 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2075 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002076 err_code |= ERR_ALERT | ERR_FATAL;
2077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002079
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002080 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002081 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002082 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002083 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002084 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 curproxy->cookie_name = strdup(args[1]);
2086 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002087
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 cur_arg = 2;
2089 while (*(args[cur_arg])) {
2090 if (!strcmp(args[cur_arg], "rewrite")) {
2091 curproxy->options |= PR_O_COOK_RW;
2092 }
2093 else if (!strcmp(args[cur_arg], "indirect")) {
2094 curproxy->options |= PR_O_COOK_IND;
2095 }
2096 else if (!strcmp(args[cur_arg], "insert")) {
2097 curproxy->options |= PR_O_COOK_INS;
2098 }
2099 else if (!strcmp(args[cur_arg], "nocache")) {
2100 curproxy->options |= PR_O_COOK_NOC;
2101 }
2102 else if (!strcmp(args[cur_arg], "postonly")) {
2103 curproxy->options |= PR_O_COOK_POST;
2104 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002105 else if (!strcmp(args[cur_arg], "preserve")) {
2106 curproxy->options2 |= PR_O2_COOK_PSV;
2107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002108 else if (!strcmp(args[cur_arg], "prefix")) {
2109 curproxy->options |= PR_O_COOK_PFX;
2110 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002111 else if (!strcmp(args[cur_arg], "domain")) {
2112 if (!*args[cur_arg + 1]) {
2113 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2114 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002115 err_code |= ERR_ALERT | ERR_FATAL;
2116 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002117 }
2118
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002119 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002120 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002121 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2122 " dots nor does not start with a dot."
2123 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002124 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002125 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002126 }
2127
2128 err = invalid_domainchar(args[cur_arg + 1]);
2129 if (err) {
2130 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2131 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002134 }
2135
Willy Tarreau68a897b2009-12-03 23:28:34 +01002136 if (!curproxy->cookie_domain) {
2137 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2138 } else {
2139 /* one domain was already specified, add another one by
2140 * building the string which will be returned along with
2141 * the cookie.
2142 */
2143 char *new_ptr;
2144 int new_len = strlen(curproxy->cookie_domain) +
2145 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2146 new_ptr = malloc(new_len);
2147 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2148 free(curproxy->cookie_domain);
2149 curproxy->cookie_domain = new_ptr;
2150 }
Willy Tarreau31936852010-10-06 16:59:56 +02002151 cur_arg++;
2152 }
2153 else if (!strcmp(args[cur_arg], "maxidle")) {
2154 unsigned int maxidle;
2155 const char *res;
2156
2157 if (!*args[cur_arg + 1]) {
2158 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2159 file, linenum, args[cur_arg]);
2160 err_code |= ERR_ALERT | ERR_FATAL;
2161 goto out;
2162 }
2163
2164 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2165 if (res) {
2166 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2167 file, linenum, *res, args[cur_arg]);
2168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
2171 curproxy->cookie_maxidle = maxidle;
2172 cur_arg++;
2173 }
2174 else if (!strcmp(args[cur_arg], "maxlife")) {
2175 unsigned int maxlife;
2176 const char *res;
2177
2178 if (!*args[cur_arg + 1]) {
2179 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2180 file, linenum, args[cur_arg]);
2181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
2183 }
2184
2185 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2186 if (res) {
2187 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2188 file, linenum, *res, args[cur_arg]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002193 cur_arg++;
2194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002196 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 +02002197 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 }
2201 cur_arg++;
2202 }
2203 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2204 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' 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 }
2208
2209 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2210 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2211 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002212 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002214
2215 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2216 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2217 file, linenum);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002221 else if (!strcmp(args[0], "persist")) { /* persist */
2222 if (*(args[1]) == 0) {
2223 Alert("parsing [%s:%d] : missing persist method.\n",
2224 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002227 }
2228
2229 if (!strncmp(args[1], "rdp-cookie", 10)) {
2230 curproxy->options2 |= PR_O2_RDPC_PRST;
2231
Emeric Brunb982a3d2010-01-04 15:45:53 +01002232 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002233 const char *beg, *end;
2234
2235 beg = args[1] + 11;
2236 end = strchr(beg, ')');
2237
2238 if (!end || end == beg) {
2239 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2240 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002243 }
2244
2245 free(curproxy->rdp_cookie_name);
2246 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2247 curproxy->rdp_cookie_len = end-beg;
2248 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002249 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002250 free(curproxy->rdp_cookie_name);
2251 curproxy->rdp_cookie_name = strdup("msts");
2252 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2253 }
2254 else { /* syntax */
2255 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2256 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002259 }
2260 }
2261 else {
2262 Alert("parsing [%s:%d] : unknown persist method.\n",
2263 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002266 }
2267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002269 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002271 if (curproxy == &defproxy) {
2272 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
2276
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002281 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 }
2286 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002287 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 curproxy->appsession_name = strdup(args[1]);
2289 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2290 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002291 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2292 if (err) {
2293 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2294 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002297 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002298 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002299
Willy Tarreau51041c72007-09-09 21:56:53 +02002300 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2301 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002302 err_code |= ERR_ALERT | ERR_ABORT;
2303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002305
2306 cur_arg = 6;
2307 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002308 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2309 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002310 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002311 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002312 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002313 } else if (!strcmp(args[cur_arg], "prefix")) {
2314 curproxy->options2 |= PR_O2_AS_PFX;
2315 } else if (!strcmp(args[cur_arg], "mode")) {
2316 if (!*args[cur_arg + 1]) {
2317 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2318 file, linenum, args[0], args[cur_arg]);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322
2323 cur_arg++;
2324 if (!strcmp(args[cur_arg], "query-string")) {
2325 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2326 curproxy->options2 |= PR_O2_AS_M_QS;
2327 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2328 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2329 curproxy->options2 |= PR_O2_AS_M_PP;
2330 } else {
2331 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002336 cur_arg++;
2337 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 } /* Url App Session */
2339 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002340 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002341 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002342
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002344 if (curproxy == &defproxy) {
2345 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 if (*(args[4]) == 0) {
2351 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2352 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002356 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 curproxy->capture_name = strdup(args[2]);
2358 curproxy->capture_namelen = strlen(curproxy->capture_name);
2359 curproxy->capture_len = atol(args[4]);
2360 if (curproxy->capture_len >= CAPTURE_LEN) {
2361 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2362 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 curproxy->capture_len = CAPTURE_LEN - 1;
2365 }
2366 curproxy->to_log |= LW_COOKIE;
2367 }
2368 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2369 struct cap_hdr *hdr;
2370
2371 if (curproxy == &defproxy) {
2372 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 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
2376
2377 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2378 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2379 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 }
2383
2384 hdr = calloc(sizeof(struct cap_hdr), 1);
2385 hdr->next = curproxy->req_cap;
2386 hdr->name = strdup(args[3]);
2387 hdr->namelen = strlen(args[3]);
2388 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002389 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 hdr->index = curproxy->nb_req_cap++;
2391 curproxy->req_cap = hdr;
2392 curproxy->to_log |= LW_REQHDR;
2393 }
2394 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2395 struct cap_hdr *hdr;
2396
2397 if (curproxy == &defproxy) {
2398 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 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 }
2402
2403 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2404 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2405 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }
2409 hdr = calloc(sizeof(struct cap_hdr), 1);
2410 hdr->next = curproxy->rsp_cap;
2411 hdr->name = strdup(args[3]);
2412 hdr->namelen = strlen(args[3]);
2413 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002414 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 hdr->index = curproxy->nb_rsp_cap++;
2416 curproxy->rsp_cap = hdr;
2417 curproxy->to_log |= LW_RSPHDR;
2418 }
2419 else {
2420 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2421 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 }
2425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002427 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002429
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 if (*(args[1]) == 0) {
2431 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2432 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
2436 curproxy->conn_retries = atol(args[1]);
2437 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002438 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002439 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002440
2441 if (curproxy == &defproxy) {
2442 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446
Willy Tarreauff011f22011-01-06 17:51:27 +01002447 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 +01002448 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2449 file, linenum, args[0]);
2450 err_code |= ERR_WARN;
2451 }
2452
Willy Tarreauff011f22011-01-06 17:51:27 +01002453 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002454
Willy Tarreauff011f22011-01-06 17:51:27 +01002455 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002456 err_code |= ERR_ALERT | ERR_ABORT;
2457 goto out;
2458 }
2459
Willy Tarreauff011f22011-01-06 17:51:27 +01002460 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2461 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002462 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002463 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002464 if (curproxy == &defproxy) {
2465 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002468 }
2469
Willy Tarreauef6494c2010-01-28 17:12:36 +01002470 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002471 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002475 }
2476
Willy Tarreauef6494c2010-01-28 17:12:36 +01002477 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002478 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2479 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002483
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002484 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002485 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002486 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002487 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002488 struct redirect_rule *rule;
2489 int cur_arg;
2490 int type = REDIRECT_TYPE_NONE;
2491 int code = 302;
2492 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002493 char *cookie = NULL;
2494 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002495 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002496
Cyril Bonté99ed3272010-01-24 23:29:44 +01002497 if (curproxy == &defproxy) {
2498 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
2501 }
2502
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002503 cur_arg = 1;
2504 while (*(args[cur_arg])) {
2505 if (!strcmp(args[cur_arg], "location")) {
2506 if (!*args[cur_arg + 1]) {
2507 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2508 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002509 err_code |= ERR_ALERT | ERR_FATAL;
2510 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002511 }
2512
2513 type = REDIRECT_TYPE_LOCATION;
2514 cur_arg++;
2515 destination = args[cur_arg];
2516 }
2517 else if (!strcmp(args[cur_arg], "prefix")) {
2518 if (!*args[cur_arg + 1]) {
2519 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2520 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002523 }
2524
2525 type = REDIRECT_TYPE_PREFIX;
2526 cur_arg++;
2527 destination = args[cur_arg];
2528 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002529 else if (!strcmp(args[cur_arg], "set-cookie")) {
2530 if (!*args[cur_arg + 1]) {
2531 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2532 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002535 }
2536
2537 cur_arg++;
2538 cookie = args[cur_arg];
2539 cookie_set = 1;
2540 }
2541 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2542 if (!*args[cur_arg + 1]) {
2543 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2544 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002547 }
2548
2549 cur_arg++;
2550 cookie = args[cur_arg];
2551 cookie_set = 0;
2552 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002553 else if (!strcmp(args[cur_arg],"code")) {
2554 if (!*args[cur_arg + 1]) {
2555 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002559 }
2560 cur_arg++;
2561 code = atol(args[cur_arg]);
2562 if (code < 301 || code > 303) {
2563 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2564 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002567 }
2568 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002569 else if (!strcmp(args[cur_arg],"drop-query")) {
2570 flags |= REDIRECT_FLAG_DROP_QS;
2571 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002572 else if (!strcmp(args[cur_arg],"append-slash")) {
2573 flags |= REDIRECT_FLAG_APPEND_SLASH;
2574 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002575 else if (strcmp(args[cur_arg], "if") == 0 ||
2576 strcmp(args[cur_arg], "unless") == 0) {
2577 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2578 if (!cond) {
2579 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2580 file, linenum, args[0]);
2581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
2583 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002584 break;
2585 }
2586 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002587 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 +02002588 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002591 }
2592 cur_arg++;
2593 }
2594
2595 if (type == REDIRECT_TYPE_NONE) {
2596 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2597 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 }
2601
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002602 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2603 rule->cond = cond;
2604 rule->rdr_str = strdup(destination);
2605 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002606 if (cookie) {
2607 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002608 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002609 */
2610 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002611 if (cookie_set) {
2612 rule->cookie_str = malloc(rule->cookie_len + 10);
2613 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2614 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2615 rule->cookie_len += 9;
2616 } else {
2617 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002618 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002619 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2620 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002621 }
2622 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002623 rule->type = type;
2624 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002625 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 LIST_INIT(&rule->list);
2627 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002628 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2629 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002630 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002631 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002632 struct switching_rule *rule;
2633
Willy Tarreaub099aca2008-10-12 17:26:37 +02002634 if (curproxy == &defproxy) {
2635 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_ALERT | ERR_FATAL;
2637 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002638 }
2639
Willy Tarreau55ea7572007-06-17 19:56:27 +02002640 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002642
2643 if (*(args[1]) == 0) {
2644 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002647 }
2648
Willy Tarreauef6494c2010-01-28 17:12:36 +01002649 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002650 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002654 }
2655
Willy Tarreauef6494c2010-01-28 17:12:36 +01002656 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002657 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002658 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002661 }
2662
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002663 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002664
Willy Tarreau55ea7572007-06-17 19:56:27 +02002665 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2666 rule->cond = cond;
2667 rule->be.name = strdup(args[1]);
2668 LIST_INIT(&rule->list);
2669 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2670 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002671 else if ((!strcmp(args[0], "force-persist")) ||
2672 (!strcmp(args[0], "ignore-persist"))) {
2673 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002674
2675 if (curproxy == &defproxy) {
2676 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2677 err_code |= ERR_ALERT | ERR_FATAL;
2678 goto out;
2679 }
2680
2681 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2682 err_code |= ERR_WARN;
2683
Willy Tarreauef6494c2010-01-28 17:12:36 +01002684 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002685 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2686 file, linenum, args[0]);
2687 err_code |= ERR_ALERT | ERR_FATAL;
2688 goto out;
2689 }
2690
Willy Tarreauef6494c2010-01-28 17:12:36 +01002691 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002692 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2693 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
2696 }
2697
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002698 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002699
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002700 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002701 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002702 if (!strcmp(args[0], "force-persist")) {
2703 rule->type = PERSIST_TYPE_FORCE;
2704 } else {
2705 rule->type = PERSIST_TYPE_IGNORE;
2706 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002707 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002708 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002709 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002710 else if (!strcmp(args[0], "stick-table")) {
2711 int myidx = 1;
2712
Emeric Brun32da3c42010-09-23 18:39:19 +02002713 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002714 curproxy->table.type = (unsigned int)-1;
2715 while (*args[myidx]) {
2716 const char *err;
2717
2718 if (strcmp(args[myidx], "size") == 0) {
2719 myidx++;
2720 if (!*(args[myidx])) {
2721 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2722 file, linenum, args[myidx-1]);
2723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
2725 }
2726 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2727 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2728 file, linenum, *err, args[myidx-1]);
2729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
2731 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002732 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002733 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002734 else if (strcmp(args[myidx], "peers") == 0) {
2735 myidx++;
2736 if (!*(args[myidx])) {
2737 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2738 file, linenum, args[myidx-1]);
2739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
2741 }
2742 curproxy->table.peers.name = strdup(args[myidx++]);
2743 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002744 else if (strcmp(args[myidx], "expire") == 0) {
2745 myidx++;
2746 if (!*(args[myidx])) {
2747 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2748 file, linenum, args[myidx-1]);
2749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
2751 }
2752 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2753 if (err) {
2754 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2755 file, linenum, *err, args[myidx-1]);
2756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
2758 }
2759 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002760 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002761 }
2762 else if (strcmp(args[myidx], "nopurge") == 0) {
2763 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002764 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002765 }
2766 else if (strcmp(args[myidx], "type") == 0) {
2767 myidx++;
2768 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2769 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2770 file, linenum, args[myidx]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002774 /* myidx already points to next arg */
2775 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002776 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002777 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002778 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002779
2780 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002781 nw = args[myidx];
2782 while (*nw) {
2783 /* the "store" keyword supports a comma-separated list */
2784 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002785 sa = NULL; /* store arg */
2786 while (*nw && *nw != ',') {
2787 if (*nw == '(') {
2788 *nw = 0;
2789 sa = ++nw;
2790 while (*nw != ')') {
2791 if (!*nw) {
2792 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2793 file, linenum, args[0], cw);
2794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
2796 }
2797 nw++;
2798 }
2799 *nw = '\0';
2800 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002801 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002802 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002803 if (*nw)
2804 *nw++ = '\0';
2805 type = stktable_get_data_type(cw);
2806 if (type < 0) {
2807 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2808 file, linenum, args[0], cw);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
Willy Tarreauac782882010-06-20 10:41:54 +02002812
2813 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2814 switch (err) {
2815 case PE_NONE: break;
2816 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002817 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2818 file, linenum, args[0], cw);
2819 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002820 break;
2821
2822 case PE_ARG_MISSING:
2823 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2824 file, linenum, args[0], cw);
2825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
2827
2828 case PE_ARG_NOT_USED:
2829 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2830 file, linenum, args[0], cw);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833
2834 default:
2835 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2836 file, linenum, args[0], cw);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002839 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002840 }
2841 myidx++;
2842 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002843 else {
2844 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2845 file, linenum, args[myidx]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002848 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002849 }
2850
2851 if (!curproxy->table.size) {
2852 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2853 file, linenum);
2854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
2856 }
2857
2858 if (curproxy->table.type == (unsigned int)-1) {
2859 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2860 file, linenum);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864 }
2865 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002866 struct sticking_rule *rule;
2867 struct pattern_expr *expr;
2868 int myidx = 0;
2869 const char *name = NULL;
2870 int flags;
2871
2872 if (curproxy == &defproxy) {
2873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877
2878 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2879 err_code |= ERR_WARN;
2880 goto out;
2881 }
2882
2883 myidx++;
2884 if ((strcmp(args[myidx], "store") == 0) ||
2885 (strcmp(args[myidx], "store-request") == 0)) {
2886 myidx++;
2887 flags = STK_IS_STORE;
2888 }
2889 else if (strcmp(args[myidx], "store-response") == 0) {
2890 myidx++;
2891 flags = STK_IS_STORE | STK_ON_RSP;
2892 }
2893 else if (strcmp(args[myidx], "match") == 0) {
2894 myidx++;
2895 flags = STK_IS_MATCH;
2896 }
2897 else if (strcmp(args[myidx], "on") == 0) {
2898 myidx++;
2899 flags = STK_IS_MATCH | STK_IS_STORE;
2900 }
2901 else {
2902 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906
2907 if (*(args[myidx]) == 0) {
2908 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
Emeric Brun485479d2010-09-23 18:02:19 +02002913 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002914 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002915 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
2918 }
2919
2920 if (flags & STK_ON_RSP) {
2921 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2922 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2923 file, linenum, args[0], expr->fetch->kw);
2924 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002925 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002926 goto out;
2927 }
2928 } else {
2929 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2930 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2931 file, linenum, args[0], expr->fetch->kw);
2932 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002933 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002934 goto out;
2935 }
2936 }
2937
2938 if (strcmp(args[myidx], "table") == 0) {
2939 myidx++;
2940 name = args[myidx++];
2941 }
2942
Willy Tarreauef6494c2010-01-28 17:12:36 +01002943 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2944 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002945 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2946 file, linenum, args[0]);
2947 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002948 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002949 goto out;
2950 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002951 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002952 else if (*(args[myidx])) {
2953 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2954 file, linenum, args[0], args[myidx]);
2955 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002956 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002957 goto out;
2958 }
Emeric Brun97679e72010-09-23 17:56:44 +02002959 if (flags & STK_ON_RSP)
2960 err_code |= warnif_cond_requires_req(cond, file, linenum);
2961 else
2962 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002963
Emeric Brunb982a3d2010-01-04 15:45:53 +01002964 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2965 rule->cond = cond;
2966 rule->expr = expr;
2967 rule->flags = flags;
2968 rule->table.name = name ? strdup(name) : NULL;
2969 LIST_INIT(&rule->list);
2970 if (flags & STK_ON_RSP)
2971 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2972 else
2973 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002978
Willy Tarreaubaaee002006-06-26 02:48:02 +02002979 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2980 curproxy->uri_auth = NULL; /* we must detach from the default config */
2981
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002982 if (!*args[1]) {
2983 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002984 } else if (!strcmp(args[1], "admin")) {
2985 struct stats_admin_rule *rule;
2986
2987 if (curproxy == &defproxy) {
2988 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
2991 }
2992
2993 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2994 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2995 err_code |= ERR_ALERT | ERR_ABORT;
2996 goto out;
2997 }
2998
2999 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3000 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3001 file, linenum, args[0], args[1]);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
3005 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3006 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3007 file, linenum, args[0], args[1]);
3008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
3010 }
3011
3012 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3013
3014 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3015 rule->cond = cond;
3016 LIST_INIT(&rule->list);
3017 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 } else if (!strcmp(args[1], "uri")) {
3019 if (*(args[2]) == 0) {
3020 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3024 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_ABORT;
3026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 }
3028 } else if (!strcmp(args[1], "realm")) {
3029 if (*(args[2]) == 0) {
3030 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3034 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_ABORT;
3036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003038 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003039 unsigned interval;
3040
3041 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3042 if (err) {
3043 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3044 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003047 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_ABORT;
3050 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003051 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003052 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003053 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003054
3055 if (curproxy == &defproxy) {
3056 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
3060
3061 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3062 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3063 err_code |= ERR_ALERT | ERR_ABORT;
3064 goto out;
3065 }
3066
Willy Tarreauff011f22011-01-06 17:51:27 +01003067 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3068 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003069 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3070 file, linenum, args[0]);
3071 err_code |= ERR_WARN;
3072 }
3073
Willy Tarreauff011f22011-01-06 17:51:27 +01003074 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003075
Willy Tarreauff011f22011-01-06 17:51:27 +01003076 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003077 err_code |= ERR_ALERT | ERR_ABORT;
3078 goto out;
3079 }
3080
Willy Tarreauff011f22011-01-06 17:51:27 +01003081 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3082 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003083
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 } else if (!strcmp(args[1], "auth")) {
3085 if (*(args[2]) == 0) {
3086 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_FATAL;
3088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3090 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_ABORT;
3092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 }
3094 } else if (!strcmp(args[1], "scope")) {
3095 if (*(args[2]) == 0) {
3096 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003099 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
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 }
3104 } else if (!strcmp(args[1], "enable")) {
3105 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003110 } else if (!strcmp(args[1], "hide-version")) {
3111 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3112 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003113 err_code |= ERR_ALERT | ERR_ABORT;
3114 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003115 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003116 } else if (!strcmp(args[1], "show-legends")) {
3117 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3118 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3119 err_code |= ERR_ALERT | ERR_ABORT;
3120 goto out;
3121 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003122 } else if (!strcmp(args[1], "show-node")) {
3123
3124 if (*args[2]) {
3125 int i;
3126 char c;
3127
3128 for (i=0; args[2][i]; i++) {
3129 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003130 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3131 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003132 break;
3133 }
3134
3135 if (!i || args[2][i]) {
3136 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3137 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3138 file, linenum, args[0], args[1]);
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
3141 }
3142 }
3143
3144 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3145 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3146 err_code |= ERR_ALERT | ERR_ABORT;
3147 goto out;
3148 }
3149 } else if (!strcmp(args[1], "show-desc")) {
3150 char *desc = NULL;
3151
3152 if (*args[2]) {
3153 int i, len=0;
3154 char *d;
3155
3156 for(i=2; *args[i]; i++)
3157 len += strlen(args[i])+1;
3158
3159 desc = d = (char *)calloc(1, len);
3160
3161 d += sprintf(d, "%s", args[2]);
3162 for(i=3; *args[i]; i++)
3163 d += sprintf(d, " %s", args[i]);
3164 }
3165
3166 if (!*args[2] && !global.desc)
3167 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3168 file, linenum, args[1]);
3169 else {
3170 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3171 free(desc);
3172 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3173 err_code |= ERR_ALERT | ERR_ABORT;
3174 goto out;
3175 }
3176 free(desc);
3177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003179stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003180 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 +01003181 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185 }
3186 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003187 int optnum;
3188
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003189 if (*(args[1]) == '\0') {
3190 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3191 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003195
3196 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3197 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003198 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3199 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3200 file, linenum, cfg_opts[optnum].name);
3201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
3203 }
Willy Tarreau93893792009-07-23 13:19:11 +02003204 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3205 err_code |= ERR_WARN;
3206 goto out;
3207 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003208
Willy Tarreau3842f002009-06-14 11:39:52 +02003209 curproxy->no_options &= ~cfg_opts[optnum].val;
3210 curproxy->options &= ~cfg_opts[optnum].val;
3211
3212 switch (kwm) {
3213 case KWM_STD:
3214 curproxy->options |= cfg_opts[optnum].val;
3215 break;
3216 case KWM_NO:
3217 curproxy->no_options |= cfg_opts[optnum].val;
3218 break;
3219 case KWM_DEF: /* already cleared */
3220 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003221 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003222
Willy Tarreau93893792009-07-23 13:19:11 +02003223 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003224 }
3225 }
3226
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003227 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3228 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003229 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3230 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3231 file, linenum, cfg_opts2[optnum].name);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
3234 }
Willy Tarreau93893792009-07-23 13:19:11 +02003235 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3236 err_code |= ERR_WARN;
3237 goto out;
3238 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003239
Willy Tarreau3842f002009-06-14 11:39:52 +02003240 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3241 curproxy->options2 &= ~cfg_opts2[optnum].val;
3242
3243 switch (kwm) {
3244 case KWM_STD:
3245 curproxy->options2 |= cfg_opts2[optnum].val;
3246 break;
3247 case KWM_NO:
3248 curproxy->no_options2 |= cfg_opts2[optnum].val;
3249 break;
3250 case KWM_DEF: /* already cleared */
3251 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003252 }
Willy Tarreau93893792009-07-23 13:19:11 +02003253 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003254 }
3255 }
3256
Willy Tarreau3842f002009-06-14 11:39:52 +02003257 if (kwm != KWM_STD) {
3258 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003259 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003262 }
3263
Emeric Brun3a058f32009-06-30 18:26:00 +02003264 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003266 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003268 if (*(args[2]) != '\0') {
3269 if (!strcmp(args[2], "clf")) {
3270 curproxy->options2 |= PR_O2_CLFLOG;
3271 } else {
3272 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
3274 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003275 }
3276 }
3277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 else if (!strcmp(args[1], "tcplog"))
3279 /* generate a detailed TCP log */
3280 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 else if (!strcmp(args[1], "tcpka")) {
3282 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003283 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003285
3286 if (curproxy->cap & PR_CAP_FE)
3287 curproxy->options |= PR_O_TCP_CLI_KA;
3288 if (curproxy->cap & PR_CAP_BE)
3289 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 }
3291 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003292 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_WARN;
3294
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003296 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003297 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003298 curproxy->options2 &= ~PR_O2_CHK_ANY;
3299 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 if (!*args[2]) { /* no argument */
3301 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3302 curproxy->check_len = strlen(DEF_CHECK_REQ);
3303 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003304 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 curproxy->check_req = (char *)malloc(reqlen);
3306 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003307 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003309 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 if (*args[4])
3311 reqlen += strlen(args[4]);
3312 else
3313 reqlen += strlen("HTTP/1.0");
3314
3315 curproxy->check_req = (char *)malloc(reqlen);
3316 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003317 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003319 }
3320 else if (!strcmp(args[1], "ssl-hello-chk")) {
3321 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003322 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003323 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003324
Willy Tarreaua534fea2008-08-03 12:19:50 +02003325 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003326 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003327 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003328 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 }
Willy Tarreau23677902007-05-08 23:50:35 +02003330 else if (!strcmp(args[1], "smtpchk")) {
3331 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003332 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003333 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003334 curproxy->options2 &= ~PR_O2_CHK_ANY;
3335 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003336
3337 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3338 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3339 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3340 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3341 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3342 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3343 curproxy->check_req = (char *)malloc(reqlen);
3344 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3345 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3346 } else {
3347 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3348 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3349 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3350 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3351 }
3352 }
3353 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003354 else if (!strcmp(args[1], "pgsql-check")) {
3355 /* use PostgreSQL request to check servers' health */
3356 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3357 err_code |= ERR_WARN;
3358
3359 free(curproxy->check_req);
3360 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003361 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003362 curproxy->options2 |= PR_O2_PGSQL_CHK;
3363
3364 if (*(args[2])) {
3365 int cur_arg = 2;
3366
3367 while (*(args[cur_arg])) {
3368 if (strcmp(args[cur_arg], "user") == 0) {
3369 char * packet;
3370 uint32_t packet_len;
3371 uint32_t pv;
3372
3373 /* suboption header - needs additional argument for it */
3374 if (*(args[cur_arg+1]) == 0) {
3375 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3376 file, linenum, args[0], args[1], args[cur_arg]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380
3381 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3382 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3383 pv = htonl(0x30000); /* protocol version 3.0 */
3384
3385 packet = (char*) calloc(1, packet_len);
3386
3387 memcpy(packet + 4, &pv, 4);
3388
3389 /* copy "user" */
3390 memcpy(packet + 8, "user", 4);
3391
3392 /* copy username */
3393 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3394
3395 free(curproxy->check_req);
3396 curproxy->check_req = packet;
3397 curproxy->check_len = packet_len;
3398
3399 packet_len = htonl(packet_len);
3400 memcpy(packet, &packet_len, 4);
3401 cur_arg += 2;
3402 } else {
3403 /* unknown suboption - catchall */
3404 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3405 file, linenum, args[0], args[1]);
3406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
3408 }
3409 } /* end while loop */
3410 }
3411 }
3412
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003413 else if (!strcmp(args[1], "redis-check")) {
3414 /* use REDIS PING request to check servers' health */
3415 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3416 err_code |= ERR_WARN;
3417
3418 free(curproxy->check_req);
3419 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003420 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003421 curproxy->options2 |= PR_O2_REDIS_CHK;
3422
3423 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3424 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3425 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3426 }
3427
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003428 else if (!strcmp(args[1], "mysql-check")) {
3429 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3431 err_code |= ERR_WARN;
3432
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003433 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003434 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003435 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003436 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003437
3438 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3439 * const char mysql40_client_auth_pkt[] = {
3440 * "\x0e\x00\x00" // packet length
3441 * "\x01" // packet number
3442 * "\x00\x00" // client capabilities
3443 * "\x00\x00\x01" // max packet
3444 * "haproxy\x00" // username (null terminated string)
3445 * "\x00" // filler (always 0x00)
3446 * "\x01\x00\x00" // packet length
3447 * "\x00" // packet number
3448 * "\x01" // COM_QUIT command
3449 * };
3450 */
3451
3452 if (*(args[2])) {
3453 int cur_arg = 2;
3454
3455 while (*(args[cur_arg])) {
3456 if (strcmp(args[cur_arg], "user") == 0) {
3457 char *mysqluser;
3458 int packetlen, reqlen, userlen;
3459
3460 /* suboption header - needs additional argument for it */
3461 if (*(args[cur_arg+1]) == 0) {
3462 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3463 file, linenum, args[0], args[1], args[cur_arg]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467 mysqluser = args[cur_arg + 1];
3468 userlen = strlen(mysqluser);
3469 packetlen = userlen + 7;
3470 reqlen = packetlen + 9;
3471
3472 free(curproxy->check_req);
3473 curproxy->check_req = (char *)calloc(1, reqlen);
3474 curproxy->check_len = reqlen;
3475
3476 snprintf(curproxy->check_req, 4, "%c%c%c",
3477 ((unsigned char) packetlen & 0xff),
3478 ((unsigned char) (packetlen >> 8) & 0xff),
3479 ((unsigned char) (packetlen >> 16) & 0xff));
3480
3481 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003482 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003483 curproxy->check_req[8] = 1;
3484 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3485 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3486 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3487 cur_arg += 2;
3488 } else {
3489 /* unknown suboption - catchall */
3490 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3491 file, linenum, args[0], args[1]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
3495 } /* end while loop */
3496 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003497 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003498 else if (!strcmp(args[1], "ldap-check")) {
3499 /* use LDAP request to check servers' health */
3500 free(curproxy->check_req);
3501 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003502 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003503 curproxy->options2 |= PR_O2_LDAP_CHK;
3504
3505 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3506 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3507 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3508 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003509 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003510 int cur_arg;
3511
3512 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3513 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003514 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003515
Willy Tarreau87cf5142011-08-19 22:57:24 +02003516 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003517
3518 free(curproxy->fwdfor_hdr_name);
3519 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3520 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3521
3522 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3523 cur_arg = 2;
3524 while (*(args[cur_arg])) {
3525 if (!strcmp(args[cur_arg], "except")) {
3526 /* suboption except - needs additional argument for it */
3527 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3528 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3529 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003532 }
3533 /* flush useless bits */
3534 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003535 cur_arg += 2;
3536 } else if (!strcmp(args[cur_arg], "header")) {
3537 /* suboption header - needs additional argument for it */
3538 if (*(args[cur_arg+1]) == 0) {
3539 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3540 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003543 }
3544 free(curproxy->fwdfor_hdr_name);
3545 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3546 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3547 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003548 } else if (!strcmp(args[cur_arg], "if-none")) {
3549 curproxy->options &= ~PR_O_FF_ALWAYS;
3550 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003551 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003552 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003553 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003554 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003557 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003558 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003559 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003560 else if (!strcmp(args[1], "originalto")) {
3561 int cur_arg;
3562
3563 /* insert x-original-to field, but not for the IP address listed as an except.
3564 * set default options (ie: bitfield, header name, etc)
3565 */
3566
3567 curproxy->options |= PR_O_ORGTO;
3568
3569 free(curproxy->orgto_hdr_name);
3570 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3571 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3572
Willy Tarreau87cf5142011-08-19 22:57:24 +02003573 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003574 cur_arg = 2;
3575 while (*(args[cur_arg])) {
3576 if (!strcmp(args[cur_arg], "except")) {
3577 /* suboption except - needs additional argument for it */
3578 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3579 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3580 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003583 }
3584 /* flush useless bits */
3585 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3586 cur_arg += 2;
3587 } else if (!strcmp(args[cur_arg], "header")) {
3588 /* suboption header - needs additional argument for it */
3589 if (*(args[cur_arg+1]) == 0) {
3590 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3591 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003594 }
3595 free(curproxy->orgto_hdr_name);
3596 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3597 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3598 cur_arg += 2;
3599 } else {
3600 /* unknown suboption - catchall */
3601 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3602 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003605 }
3606 } /* end while loop */
3607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 else {
3609 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 }
Willy Tarreau93893792009-07-23 13:19:11 +02003613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003615 else if (!strcmp(args[0], "default_backend")) {
3616 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003618
3619 if (*(args[1]) == 0) {
3620 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003623 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003624 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003625 curproxy->defbe.name = strdup(args[1]);
3626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003628 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003630
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003631 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3632 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 /* enable reconnections to dispatch */
3635 curproxy->options |= PR_O_REDISP;
3636 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003637 else if (!strcmp(args[0], "http-check")) {
3638 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003639 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003640
3641 if (strcmp(args[1], "disable-on-404") == 0) {
3642 /* enable a graceful server shutdown on an HTTP 404 response */
3643 curproxy->options |= PR_O_DISABLE404;
3644 }
Willy Tarreauef781042010-01-27 11:53:01 +01003645 else if (strcmp(args[1], "send-state") == 0) {
3646 /* enable emission of the apparent state of a server in HTTP checks */
3647 curproxy->options2 |= PR_O2_CHK_SNDST;
3648 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003649 else if (strcmp(args[1], "expect") == 0) {
3650 const char *ptr_arg;
3651 int cur_arg;
3652
3653 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3654 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
3657 }
3658
3659 cur_arg = 2;
3660 /* consider exclamation marks, sole or at the beginning of a word */
3661 while (*(ptr_arg = args[cur_arg])) {
3662 while (*ptr_arg == '!') {
3663 curproxy->options2 ^= PR_O2_EXP_INV;
3664 ptr_arg++;
3665 }
3666 if (*ptr_arg)
3667 break;
3668 cur_arg++;
3669 }
3670 /* now ptr_arg points to the beginning of a word past any possible
3671 * exclamation mark, and cur_arg is the argument which holds this word.
3672 */
3673 if (strcmp(ptr_arg, "status") == 0) {
3674 if (!*(args[cur_arg + 1])) {
3675 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3676 file, linenum, args[0], args[1], ptr_arg);
3677 err_code |= ERR_ALERT | ERR_FATAL;
3678 goto out;
3679 }
3680 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003681 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003682 curproxy->expect_str = strdup(args[cur_arg + 1]);
3683 }
3684 else if (strcmp(ptr_arg, "string") == 0) {
3685 if (!*(args[cur_arg + 1])) {
3686 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3687 file, linenum, args[0], args[1], ptr_arg);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
3691 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003692 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003693 curproxy->expect_str = strdup(args[cur_arg + 1]);
3694 }
3695 else if (strcmp(ptr_arg, "rstatus") == 0) {
3696 if (!*(args[cur_arg + 1])) {
3697 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3698 file, linenum, args[0], args[1], ptr_arg);
3699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
3701 }
3702 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003703 free(curproxy->expect_str);
3704 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3705 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003706 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3707 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3708 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3709 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
3712 }
3713 }
3714 else if (strcmp(ptr_arg, "rstring") == 0) {
3715 if (!*(args[cur_arg + 1])) {
3716 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3717 file, linenum, args[0], args[1], ptr_arg);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003722 free(curproxy->expect_str);
3723 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3724 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003725 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3726 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3727 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3728 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3729 err_code |= ERR_ALERT | ERR_FATAL;
3730 goto out;
3731 }
3732 }
3733 else {
3734 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3735 file, linenum, args[0], args[1], ptr_arg);
3736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
3738 }
3739 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003740 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003741 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 +02003742 err_code |= ERR_ALERT | ERR_FATAL;
3743 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003744 }
3745 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003746 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003747 if (curproxy == &defproxy) {
3748 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003751 }
3752
Willy Tarreaub80c2302007-11-30 20:51:32 +01003753 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003755
3756 if (strcmp(args[1], "fail") == 0) {
3757 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003758 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003759 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3760 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_ALERT | ERR_FATAL;
3762 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003763 }
3764
Willy Tarreauef6494c2010-01-28 17:12:36 +01003765 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003766 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3767 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003770 }
3771 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3772 }
3773 else {
3774 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003777 }
3778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779#ifdef TPROXY
3780 else if (!strcmp(args[0], "transparent")) {
3781 /* enable transparent proxy connections */
3782 curproxy->options |= PR_O_TRANSP;
3783 }
3784#endif
3785 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003786 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003788
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 if (*(args[1]) == 0) {
3790 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003793 }
3794 curproxy->maxconn = atol(args[1]);
3795 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003796 else if (!strcmp(args[0], "backlog")) { /* backlog */
3797 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003799
3800 if (*(args[1]) == 0) {
3801 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003804 }
3805 curproxy->backlog = atol(args[1]);
3806 }
Willy Tarreau86034312006-12-29 00:10:33 +01003807 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003808 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003810
Willy Tarreau86034312006-12-29 00:10:33 +01003811 if (*(args[1]) == 0) {
3812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003815 }
3816 curproxy->fullconn = atol(args[1]);
3817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3819 if (*(args[1]) == 0) {
3820 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003824 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3825 if (err) {
3826 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3827 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003830 }
3831 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 }
3833 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003834 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 if (curproxy == &defproxy) {
3836 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003840 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003842
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 if (strchr(args[1], ':') == NULL) {
3844 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003848 sk = str2sa(args[1]);
3849 if (!sk) {
3850 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
3853 }
3854 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003855 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 }
3857 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003858 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003860
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003861 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003862 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3863 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003866 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003868 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3869 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3870 err_code |= ERR_WARN;
3871
3872 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3873 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3874 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3875 }
3876 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3877 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3878 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3879 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003880 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3881 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3882 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3883 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003884 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003885 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003890 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003892 char *rport, *raddr;
3893 short realport = 0;
3894 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003896 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003901 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003903
3904 if (!*args[2]) {
3905 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3906 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003907 err_code |= ERR_ALERT | ERR_FATAL;
3908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003910
3911 err = invalid_char(args[1]);
3912 if (err) {
3913 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3914 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003917 }
3918
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003919 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003920 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003921
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003922 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3923 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3924 err_code |= ERR_ALERT | ERR_ABORT;
3925 goto out;
3926 }
3927
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 /* the servers are linked backwards first */
3929 newsrv->next = curproxy->srv;
3930 curproxy->srv = newsrv;
3931 newsrv->proxy = curproxy;
3932 newsrv->conf.file = file;
3933 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934
Simon Hormanaf514952011-06-21 14:34:57 +09003935 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003936 LIST_INIT(&newsrv->pendconns);
3937 do_check = 0;
3938 newsrv->state = SRV_RUNNING; /* early server setup */
3939 newsrv->last_change = now.tv_sec;
3940 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003942 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003943 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003944 * - IP: => port=+0, relative
3945 * - IP:N => port=N, absolute
3946 * - IP:+N => port=+N, relative
3947 * - IP:-N => port=-N, relative
3948 */
3949 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003950 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003951 if (rport) {
3952 *rport++ = 0;
3953 realport = atol(rport);
3954 if (!isdigit((unsigned char)*rport))
3955 newsrv->state |= SRV_MAPPORTS;
3956 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003958
Willy Tarreaufab5a432011-03-04 15:31:53 +01003959 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003960 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003961 if (!sk) {
3962 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
3965 }
3966 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003967 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003968
3969 newsrv->check_port = curproxy->defsrv.check_port;
3970 newsrv->inter = curproxy->defsrv.inter;
3971 newsrv->fastinter = curproxy->defsrv.fastinter;
3972 newsrv->downinter = curproxy->defsrv.downinter;
3973 newsrv->rise = curproxy->defsrv.rise;
3974 newsrv->fall = curproxy->defsrv.fall;
3975 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3976 newsrv->minconn = curproxy->defsrv.minconn;
3977 newsrv->maxconn = curproxy->defsrv.maxconn;
3978 newsrv->slowstart = curproxy->defsrv.slowstart;
3979 newsrv->onerror = curproxy->defsrv.onerror;
3980 newsrv->consecutive_errors_limit
3981 = curproxy->defsrv.consecutive_errors_limit;
3982 newsrv->uweight = newsrv->iweight
3983 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003984
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003985 newsrv->curfd = -1; /* no health-check in progress */
3986 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003988 cur_arg = 3;
3989 } else {
3990 newsrv = &curproxy->defsrv;
3991 cur_arg = 1;
3992 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003993
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003995 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003996 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003997
3998 if (!*args[cur_arg + 1]) {
3999 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4000 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004003 }
4004
4005 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004006 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004007
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004008 if (newsrv->puid <= 0) {
4009 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004010 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004013 }
4014
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004015 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4016 if (node) {
4017 struct server *target = container_of(node, struct server, conf.id);
4018 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4019 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4020 err_code |= ERR_ALERT | ERR_FATAL;
4021 goto out;
4022 }
4023 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004024 cur_arg += 2;
4025 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004026 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 newsrv->cookie = strdup(args[cur_arg + 1]);
4028 newsrv->cklen = strlen(args[cur_arg + 1]);
4029 cur_arg += 2;
4030 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004031 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004032 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4033 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4034 cur_arg += 2;
4035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004037 if (!*args[cur_arg + 1]) {
4038 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4039 file, linenum, args[cur_arg]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
4043
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004045 if (newsrv->rise <= 0) {
4046 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4047 file, linenum, args[cur_arg]);
4048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
4050 }
4051
Willy Tarreau96839092010-03-29 10:02:24 +02004052 if (newsrv->health)
4053 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004054 cur_arg += 2;
4055 }
4056 else if (!strcmp(args[cur_arg], "fall")) {
4057 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004058
4059 if (!*args[cur_arg + 1]) {
4060 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4061 file, linenum, args[cur_arg]);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065
4066 if (newsrv->fall <= 0) {
4067 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4068 file, linenum, args[cur_arg]);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 cur_arg += 2;
4074 }
4075 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004076 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4077 if (err) {
4078 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4079 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004080 err_code |= ERR_ALERT | ERR_FATAL;
4081 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004082 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004083 if (val <= 0) {
4084 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4085 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004088 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004089 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004090 cur_arg += 2;
4091 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004092 else if (!strcmp(args[cur_arg], "fastinter")) {
4093 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4094 if (err) {
4095 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4096 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004099 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004100 if (val <= 0) {
4101 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4102 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004105 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004106 newsrv->fastinter = val;
4107 cur_arg += 2;
4108 }
4109 else if (!strcmp(args[cur_arg], "downinter")) {
4110 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4111 if (err) {
4112 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4113 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004116 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004117 if (val <= 0) {
4118 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4119 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004122 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004123 newsrv->downinter = val;
4124 cur_arg += 2;
4125 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004126 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004127 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004128 if (!sk) {
4129 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4130 err_code |= ERR_ALERT | ERR_FATAL;
4131 goto out;
4132 }
4133 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004134 cur_arg += 2;
4135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 else if (!strcmp(args[cur_arg], "port")) {
4137 newsrv->check_port = atol(args[cur_arg + 1]);
4138 cur_arg += 2;
4139 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004140 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 newsrv->state |= SRV_BACKUP;
4142 cur_arg ++;
4143 }
Simon Hormanfa461682011-06-25 09:39:49 +09004144 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4145 newsrv->state |= SRV_NON_STICK;
4146 cur_arg ++;
4147 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004148 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4149 newsrv->state |= SRV_SEND_PROXY;
4150 cur_arg ++;
4151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004152 else if (!strcmp(args[cur_arg], "weight")) {
4153 int w;
4154 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004155 if (w < 0 || w > 256) {
4156 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004157 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004161 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 cur_arg += 2;
4163 }
4164 else if (!strcmp(args[cur_arg], "minconn")) {
4165 newsrv->minconn = atol(args[cur_arg + 1]);
4166 cur_arg += 2;
4167 }
4168 else if (!strcmp(args[cur_arg], "maxconn")) {
4169 newsrv->maxconn = atol(args[cur_arg + 1]);
4170 cur_arg += 2;
4171 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004172 else if (!strcmp(args[cur_arg], "maxqueue")) {
4173 newsrv->maxqueue = atol(args[cur_arg + 1]);
4174 cur_arg += 2;
4175 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004176 else if (!strcmp(args[cur_arg], "slowstart")) {
4177 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004178 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004179 if (err) {
4180 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4181 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004184 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004185 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004186 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4187 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004188 err_code |= ERR_ALERT | ERR_FATAL;
4189 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004190 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004191 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004192 cur_arg += 2;
4193 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004194 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004195
4196 if (!*args[cur_arg + 1]) {
4197 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4198 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004199 err_code |= ERR_ALERT | ERR_FATAL;
4200 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004201 }
4202
4203 newsrv->trackit = strdup(args[cur_arg + 1]);
4204
4205 cur_arg += 2;
4206 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004207 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 global.maxsock++;
4209 do_check = 1;
4210 cur_arg += 1;
4211 }
Willy Tarreau96839092010-03-29 10:02:24 +02004212 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4213 newsrv->state |= SRV_MAINTAIN;
4214 newsrv->state &= ~SRV_RUNNING;
4215 newsrv->health = 0;
4216 cur_arg += 1;
4217 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004218 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004219 if (!strcmp(args[cur_arg + 1], "none"))
4220 newsrv->observe = HANA_OBS_NONE;
4221 else if (!strcmp(args[cur_arg + 1], "layer4"))
4222 newsrv->observe = HANA_OBS_LAYER4;
4223 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4224 if (curproxy->mode != PR_MODE_HTTP) {
4225 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4226 file, linenum, args[cur_arg + 1]);
4227 err_code |= ERR_ALERT;
4228 }
4229 newsrv->observe = HANA_OBS_LAYER7;
4230 }
4231 else {
4232 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004233 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004234 file, linenum, args[cur_arg], args[cur_arg + 1]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 }
4238
4239 cur_arg += 2;
4240 }
4241 else if (!strcmp(args[cur_arg], "on-error")) {
4242 if (!strcmp(args[cur_arg + 1], "fastinter"))
4243 newsrv->onerror = HANA_ONERR_FASTINTER;
4244 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4245 newsrv->onerror = HANA_ONERR_FAILCHK;
4246 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4247 newsrv->onerror = HANA_ONERR_SUDDTH;
4248 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4249 newsrv->onerror = HANA_ONERR_MARKDWN;
4250 else {
4251 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004252 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004253 file, linenum, args[cur_arg], args[cur_arg + 1]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257
4258 cur_arg += 2;
4259 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004260 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4261 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4262 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4263 else {
4264 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4265 file, linenum, args[cur_arg], args[cur_arg + 1]);
4266 err_code |= ERR_ALERT | ERR_FATAL;
4267 goto out;
4268 }
4269
4270 cur_arg += 2;
4271 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004272 else if (!strcmp(args[cur_arg], "error-limit")) {
4273 if (!*args[cur_arg + 1]) {
4274 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4275 file, linenum, args[cur_arg]);
4276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
4280 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4281
4282 if (newsrv->consecutive_errors_limit <= 0) {
4283 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4284 file, linenum, args[cur_arg]);
4285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004288 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004289 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004290 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004291 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004292 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004293
Willy Tarreaubaaee002006-06-26 02:48:02 +02004294 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004295#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004296 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004297 file, linenum, "source", "usesrc");
4298#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004299 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004301#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004304 }
4305 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004306 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4307 if (!sk) {
4308 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
4312 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004313
4314 if (port_low != port_high) {
4315 int i;
4316 if (port_low <= 0 || port_low > 65535 ||
4317 port_high <= 0 || port_high > 65535 ||
4318 port_low > port_high) {
4319 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4320 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004323 }
4324 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4325 for (i = 0; i < newsrv->sport_range->size; i++)
4326 newsrv->sport_range->ports[i] = port_low + i;
4327 }
4328
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004330 while (*(args[cur_arg])) {
4331 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004332#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4333#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004334 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4335 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4336 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004339 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004340#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004341 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004342 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004343 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004346 }
4347 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004348 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004349 newsrv->state |= SRV_TPROXY_CLI;
4350 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004351 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004352 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004353 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4354 char *name, *end;
4355
4356 name = args[cur_arg+1] + 7;
4357 while (isspace(*name))
4358 name++;
4359
4360 end = name;
4361 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4362 end++;
4363
4364 newsrv->state &= ~SRV_TPROXY_MASK;
4365 newsrv->state |= SRV_TPROXY_DYN;
4366 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4367 newsrv->bind_hdr_len = end - name;
4368 memcpy(newsrv->bind_hdr_name, name, end - name);
4369 newsrv->bind_hdr_name[end-name] = '\0';
4370 newsrv->bind_hdr_occ = -1;
4371
4372 /* now look for an occurrence number */
4373 while (isspace(*end))
4374 end++;
4375 if (*end == ',') {
4376 end++;
4377 name = end;
4378 if (*end == '-')
4379 end++;
4380 while (isdigit(*end))
4381 end++;
4382 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4383 }
4384
4385 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4386 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4387 " occurrences values smaller than %d.\n",
4388 file, linenum, MAX_HDR_HISTORY);
4389 err_code |= ERR_ALERT | ERR_FATAL;
4390 goto out;
4391 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004392 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004393 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004394 if (!sk) {
4395 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004400 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004401 }
4402 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004403#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004404 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004405#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004406 cur_arg += 2;
4407 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004408#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004409 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004410 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4414 } /* "usesrc" */
4415
4416 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4417#ifdef SO_BINDTODEVICE
4418 if (!*args[cur_arg + 1]) {
4419 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4420 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004421 err_code |= ERR_ALERT | ERR_FATAL;
4422 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004423 }
4424 if (newsrv->iface_name)
4425 free(newsrv->iface_name);
4426
4427 newsrv->iface_name = strdup(args[cur_arg + 1]);
4428 newsrv->iface_len = strlen(newsrv->iface_name);
4429 global.last_checks |= LSTCHK_NETADM;
4430#else
4431 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4432 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004435#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004436 cur_arg += 2;
4437 continue;
4438 }
4439 /* this keyword in not an option of "source" */
4440 break;
4441 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004443 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004444 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4445 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004448 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004450 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004451 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 +01004452 file, linenum, newsrv->id);
4453 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004454 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 +01004455 file, linenum);
4456
Willy Tarreau93893792009-07-23 13:19:11 +02004457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004459 }
4460 }
4461
4462 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004463 if (newsrv->trackit) {
4464 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4465 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004468 }
4469
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004470 /* try to get the port from check_addr if check_port not set */
4471 if (!newsrv->check_port)
4472 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004473
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4475 newsrv->check_port = realport; /* by default */
4476 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004477 /* not yet valid, because no port was set on
4478 * the server either. We'll check if we have
4479 * a known port on the first listener.
4480 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004481 struct listener *l = curproxy->listen;
4482 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4483 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004484 }
4485 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4487 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004491
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004492 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004493 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004494 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4495 err_code |= ERR_ALERT | ERR_ABORT;
4496 goto out;
4497 }
4498
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004499 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 newsrv->state |= SRV_CHECKED;
4501 }
4502
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004503 if (!defsrv) {
4504 if (newsrv->state & SRV_BACKUP)
4505 curproxy->srv_bck++;
4506 else
4507 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004508
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004509 newsrv->prev_state = newsrv->state;
4510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 }
William Lallemand0f99e342011-10-12 17:50:54 +02004512 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4513 /* delete previous herited or defined syslog servers */
4514 struct logsrv *back;
4515
4516 if (*(args[1]) != 0) {
4517 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
4520 }
4521
4522 list_for_each_entry_safe(tmp, back, &curproxy->logsrvs, list) {
4523 LIST_DEL(&tmp->list);
4524 free(tmp);
4525 }
4526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004528 struct logsrv *logsrv;
4529
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004531 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
4532 list_for_each_entry(tmp, &global.logsrvs, list) {
4533 struct logsrv *node = malloc(sizeof(struct logsrv));
4534 memcpy(node, tmp, sizeof(struct logsrv));
4535 LIST_INIT(&node->list);
4536 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004538 }
4539 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004540
4541 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542
William Lallemand0f99e342011-10-12 17:50:54 +02004543 logsrv->facility = get_log_facility(args[2]);
4544 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
4548
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549 }
4550
William Lallemand0f99e342011-10-12 17:50:54 +02004551 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004552 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004553 logsrv->level = get_log_level(args[3]);
4554 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004555 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
4558
Willy Tarreaubaaee002006-06-26 02:48:02 +02004559 }
4560 }
4561
William Lallemand0f99e342011-10-12 17:50:54 +02004562 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004563 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004564 logsrv->minlvl = get_log_level(args[4]);
4565 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004566 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004567 err_code |= ERR_ALERT | ERR_FATAL;
4568 goto out;
4569
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004570 }
4571 }
4572
Robert Tsai81ae1952007-12-05 10:47:29 +01004573 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004574 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004575 if (!sk) {
4576 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004577 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004578 err_code |= ERR_ALERT | ERR_FATAL;
4579 goto out;
4580 }
William Lallemand0f99e342011-10-12 17:50:54 +02004581 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004582 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004583 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004584 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004585 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
4588 }
William Lallemand0f99e342011-10-12 17:50:54 +02004589 logsrv->addr = *sk;
4590 if (!get_host_port(&logsrv->addr))
4591 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
William Lallemand0f99e342011-10-12 17:50:54 +02004593
4594 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596 else {
4597 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4598 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 }
4602 }
4603 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004604 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004605 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004606
Willy Tarreau977b8e42006-12-29 14:19:17 +01004607 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004608 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004609
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004611 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4612 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004615 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004616
4617 /* we must first clear any optional default setting */
4618 curproxy->options &= ~PR_O_TPXY_MASK;
4619 free(curproxy->iface_name);
4620 curproxy->iface_name = NULL;
4621 curproxy->iface_len = 0;
4622
Willy Tarreaud5191e72010-02-09 20:50:45 +01004623 sk = str2sa(args[1]);
4624 if (!sk) {
4625 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4626 err_code |= ERR_ALERT | ERR_FATAL;
4627 goto out;
4628 }
4629 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631
4632 cur_arg = 2;
4633 while (*(args[cur_arg])) {
4634 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004635#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4636#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004637 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4638 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4639 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004642 }
4643#endif
4644 if (!*args[cur_arg + 1]) {
4645 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4646 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004649 }
4650
4651 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004652 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004653 curproxy->options |= PR_O_TPXY_CLI;
4654 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004655 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004656 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004657 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4658 char *name, *end;
4659
4660 name = args[cur_arg+1] + 7;
4661 while (isspace(*name))
4662 name++;
4663
4664 end = name;
4665 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4666 end++;
4667
4668 curproxy->options &= ~PR_O_TPXY_MASK;
4669 curproxy->options |= PR_O_TPXY_DYN;
4670 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4671 curproxy->bind_hdr_len = end - name;
4672 memcpy(curproxy->bind_hdr_name, name, end - name);
4673 curproxy->bind_hdr_name[end-name] = '\0';
4674 curproxy->bind_hdr_occ = -1;
4675
4676 /* now look for an occurrence number */
4677 while (isspace(*end))
4678 end++;
4679 if (*end == ',') {
4680 end++;
4681 name = end;
4682 if (*end == '-')
4683 end++;
4684 while (isdigit(*end))
4685 end++;
4686 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4687 }
4688
4689 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4690 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4691 " occurrences values smaller than %d.\n",
4692 file, linenum, MAX_HDR_HISTORY);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004696 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004697 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004698 if (!sk) {
4699 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
4702 }
4703 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004704 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004705 }
4706 global.last_checks |= LSTCHK_NETADM;
4707#if !defined(CONFIG_HAP_LINUX_TPROXY)
4708 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004709#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004710#else /* no TPROXY support */
4711 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004712 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715#endif
4716 cur_arg += 2;
4717 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004718 }
4719
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004720 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4721#ifdef SO_BINDTODEVICE
4722 if (!*args[cur_arg + 1]) {
4723 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4724 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004727 }
4728 if (curproxy->iface_name)
4729 free(curproxy->iface_name);
4730
4731 curproxy->iface_name = strdup(args[cur_arg + 1]);
4732 curproxy->iface_len = strlen(curproxy->iface_name);
4733 global.last_checks |= LSTCHK_NETADM;
4734#else
4735 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4736 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004739#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004740 cur_arg += 2;
4741 continue;
4742 }
4743 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4744 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004749 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4750 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4751 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004752 err_code |= ERR_ALERT | ERR_FATAL;
4753 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004756 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4758 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004761 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004762
4763 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4764 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004765 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004766 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 }
4769 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004770 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4771 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004772 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004775 }
4776 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004777 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4778 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004779 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 }
4783 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004784 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4785 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004786 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 }
4790 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004791 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4792 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004793 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004794 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004796 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004797 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4799 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004800 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004801 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004802 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004803 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004804 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4806 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004807 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004809 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004810 }
4811 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4813 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004814 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004816 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004818 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4821 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825
4826 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4827 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004828 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004829 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004831 }
4832 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4834 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004835 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 }
4839 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4841 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004842 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004843 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 }
4846 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4848 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004849 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004850 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 }
4853 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4855 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004856 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004860 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4862 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004863 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004865 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004866 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004868 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004869
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 if (curproxy == &defproxy) {
4871 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004875 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 if (*(args[1]) == 0) {
4879 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004883
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004884 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4885 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4886 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4887 file, linenum, args[0]);
4888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
4890 }
4891 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4892 }
4893 else if (*args[2]) {
4894 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4895 file, linenum, args[0], args[2]);
4896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
4898 }
4899
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004900 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004901 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004902 wl->s = strdup(args[1]);
4903 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004904 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 }
4906 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4909 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004910 err_code |= ERR_ALERT | ERR_FATAL;
4911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004913
Willy Tarreauade5ec42010-01-28 19:33:49 +01004914 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4915 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004916 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919 }
4920 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4922 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004923 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 }
4927 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4929 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004930 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
4934 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4937 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 }
4941
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4943 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004944 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004946 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 }
4948 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4950 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004951 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 }
4955 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4957 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004958 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004960 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 }
4962 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004963 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004964
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 if (curproxy == &defproxy) {
4966 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004967 err_code |= ERR_ALERT | ERR_FATAL;
4968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004970 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004971 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 if (*(args[1]) == 0) {
4974 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 }
4978
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004979 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4980 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4981 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4982 file, linenum, args[0]);
4983 err_code |= ERR_ALERT | ERR_FATAL;
4984 goto out;
4985 }
4986 err_code |= warnif_cond_requires_req(cond, file, linenum);
4987 }
4988 else if (*args[2]) {
4989 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4990 file, linenum, args[0], args[2]);
4991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
4994
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004995 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004996 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004997 wl->s = strdup(args[1]);
4998 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 }
5000 else if (!strcmp(args[0], "errorloc") ||
5001 !strcmp(args[0], "errorloc302") ||
5002 !strcmp(args[0], "errorloc303")) { /* error location */
5003 int errnum, errlen;
5004 char *err;
5005
Willy Tarreau977b8e42006-12-29 14:19:17 +01005006 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005008
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005010 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 }
5014
5015 errnum = atol(args[1]);
5016 if (!strcmp(args[0], "errorloc303")) {
5017 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5018 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5019 } else {
5020 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5021 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5022 }
5023
Willy Tarreau0f772532006-12-23 20:51:41 +01005024 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5025 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005026 chunk_destroy(&curproxy->errmsg[rc]);
5027 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005028 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005031
5032 if (rc >= HTTP_ERR_SIZE) {
5033 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5034 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 free(err);
5036 }
5037 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005038 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5039 int errnum, errlen, fd;
5040 char *err;
5041 struct stat stat;
5042
5043 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005045
5046 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005047 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
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
5052 fd = open(args[2], O_RDONLY);
5053 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5054 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5055 file, linenum, args[2], args[1]);
5056 if (fd >= 0)
5057 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005060 }
5061
Willy Tarreau27a674e2009-08-17 07:23:33 +02005062 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005063 errlen = stat.st_size;
5064 } else {
5065 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005066 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005068 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005069 }
5070
5071 err = malloc(errlen); /* malloc() must succeed during parsing */
5072 errnum = read(fd, err, errlen);
5073 if (errnum != errlen) {
5074 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5075 file, linenum, args[2], args[1]);
5076 close(fd);
5077 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005080 }
5081 close(fd);
5082
5083 errnum = atol(args[1]);
5084 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5085 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005086 chunk_destroy(&curproxy->errmsg[rc]);
5087 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005088 break;
5089 }
5090 }
5091
5092 if (rc >= HTTP_ERR_SIZE) {
5093 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5094 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005096 free(err);
5097 }
5098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005100 struct cfg_kw_list *kwl;
5101 int index;
5102
5103 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5104 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5105 if (kwl->kw[index].section != CFG_LISTEN)
5106 continue;
5107 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5108 /* prepare error message just in case */
5109 snprintf(trash, sizeof(trash),
5110 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005111 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5112 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005113 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005116 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005117 else if (rc > 0) {
5118 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_WARN;
5120 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005121 }
Willy Tarreau93893792009-07-23 13:19:11 +02005122 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005123 }
5124 }
5125 }
5126
Willy Tarreau6daf3432008-01-22 16:44:08 +01005127 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 }
Willy Tarreau93893792009-07-23 13:19:11 +02005131 out:
5132 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133}
5134
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005135int
5136cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5137{
5138
5139 int err_code = 0;
5140 const char *err;
5141
5142 if (!strcmp(args[0], "userlist")) { /* new userlist */
5143 struct userlist *newul;
5144
5145 if (!*args[1]) {
5146 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5147 file, linenum, args[0]);
5148 err_code |= ERR_ALERT | ERR_FATAL;
5149 goto out;
5150 }
5151
5152 err = invalid_char(args[1]);
5153 if (err) {
5154 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5155 file, linenum, *err, args[0], args[1]);
5156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
5158 }
5159
5160 for (newul = userlist; newul; newul = newul->next)
5161 if (!strcmp(newul->name, args[1])) {
5162 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5163 file, linenum, args[1]);
5164 err_code |= ERR_WARN;
5165 goto out;
5166 }
5167
5168 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5169 if (!newul) {
5170 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5171 err_code |= ERR_ALERT | ERR_ABORT;
5172 goto out;
5173 }
5174
5175 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5176 newul->name = strdup(args[1]);
5177
5178 if (!newul->groupusers | !newul->name) {
5179 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5180 err_code |= ERR_ALERT | ERR_ABORT;
5181 goto out;
5182 }
5183
5184 newul->next = userlist;
5185 userlist = newul;
5186
5187 } else if (!strcmp(args[0], "group")) { /* new group */
5188 int cur_arg, i;
5189 const char *err;
5190
5191 if (!*args[1]) {
5192 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5193 file, linenum, args[0]);
5194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
5196 }
5197
5198 err = invalid_char(args[1]);
5199 if (err) {
5200 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5201 file, linenum, *err, args[0], args[1]);
5202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205
5206 for(i = 0; i < userlist->grpcnt; i++)
5207 if (!strcmp(userlist->groups[i], args[1])) {
5208 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5209 file, linenum, args[1], userlist->name);
5210 err_code |= ERR_ALERT;
5211 goto out;
5212 }
5213
5214 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5215 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5216 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
5219 }
5220
5221 cur_arg = 2;
5222
5223 while (*args[cur_arg]) {
5224 if (!strcmp(args[cur_arg], "users")) {
5225 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5226 cur_arg += 2;
5227 continue;
5228 } else {
5229 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5230 file, linenum, args[0]);
5231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
5233 }
5234 }
5235
5236 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5237 } else if (!strcmp(args[0], "user")) { /* new user */
5238 struct auth_users *newuser;
5239 int cur_arg;
5240
5241 if (!*args[1]) {
5242 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5243 file, linenum, args[0]);
5244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246 }
5247
5248 for (newuser = userlist->users; newuser; newuser = newuser->next)
5249 if (!strcmp(newuser->user, args[1])) {
5250 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5251 file, linenum, args[1], userlist->name);
5252 err_code |= ERR_ALERT;
5253 goto out;
5254 }
5255
5256 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5257 if (!newuser) {
5258 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5259 err_code |= ERR_ALERT | ERR_ABORT;
5260 goto out;
5261 }
5262
5263 newuser->user = strdup(args[1]);
5264
5265 newuser->next = userlist->users;
5266 userlist->users = newuser;
5267
5268 cur_arg = 2;
5269
5270 while (*args[cur_arg]) {
5271 if (!strcmp(args[cur_arg], "password")) {
5272#ifndef CONFIG_HAP_CRYPT
5273 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5274 file, linenum);
5275 err_code |= ERR_ALERT;
5276#endif
5277 newuser->pass = strdup(args[cur_arg + 1]);
5278 cur_arg += 2;
5279 continue;
5280 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5281 newuser->pass = strdup(args[cur_arg + 1]);
5282 newuser->flags |= AU_O_INSECURE;
5283 cur_arg += 2;
5284 continue;
5285 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005286 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005287 cur_arg += 2;
5288 continue;
5289 } else {
5290 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5291 file, linenum, args[0]);
5292 err_code |= ERR_ALERT | ERR_FATAL;
5293 goto out;
5294 }
5295 }
5296 } else {
5297 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5298 err_code |= ERR_ALERT | ERR_FATAL;
5299 }
5300
5301out:
5302 return err_code;
5303}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304
5305/*
5306 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005307 * Returns the error code, 0 if OK, or any combination of :
5308 * - ERR_ABORT: must abort ASAP
5309 * - ERR_FATAL: we can continue parsing but not start the service
5310 * - ERR_WARN: a warning has been emitted
5311 * - ERR_ALERT: an alert has been emitted
5312 * Only the two first ones can stop processing, the two others are just
5313 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005315int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005316{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005317 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 FILE *f;
5319 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005321 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322
Willy Tarreaubaaee002006-06-26 02:48:02 +02005323 if ((f=fopen(file,"r")) == NULL)
5324 return -1;
5325
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005326 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005327 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005328 char *end;
5329 char *args[MAX_LINE_ARGS + 1];
5330 char *line = thisline;
5331
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 linenum++;
5333
5334 end = line + strlen(line);
5335
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005336 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5337 /* Check if we reached the limit and the last char is not \n.
5338 * Watch out for the last line without the terminating '\n'!
5339 */
5340 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005341 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005342 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005343 }
5344
Willy Tarreaubaaee002006-06-26 02:48:02 +02005345 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005346 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 line++;
5348
5349 arg = 0;
5350 args[arg] = line;
5351
5352 while (*line && arg < MAX_LINE_ARGS) {
5353 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5354 * C equivalent value. Other combinations left unchanged (eg: \1).
5355 */
5356 if (*line == '\\') {
5357 int skip = 0;
5358 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5359 *line = line[1];
5360 skip = 1;
5361 }
5362 else if (line[1] == 'r') {
5363 *line = '\r';
5364 skip = 1;
5365 }
5366 else if (line[1] == 'n') {
5367 *line = '\n';
5368 skip = 1;
5369 }
5370 else if (line[1] == 't') {
5371 *line = '\t';
5372 skip = 1;
5373 }
5374 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005375 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 unsigned char hex1, hex2;
5377 hex1 = toupper(line[2]) - '0';
5378 hex2 = toupper(line[3]) - '0';
5379 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5380 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5381 *line = (hex1<<4) + hex2;
5382 skip = 3;
5383 }
5384 else {
5385 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005386 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005387 }
5388 }
5389 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005390 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 end -= skip;
5392 }
5393 line++;
5394 }
5395 else if (*line == '#' || *line == '\n' || *line == '\r') {
5396 /* end of string, end of loop */
5397 *line = 0;
5398 break;
5399 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005400 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005401 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005402 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005403 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005404 line++;
5405 args[++arg] = line;
5406 }
5407 else {
5408 line++;
5409 }
5410 }
5411
5412 /* empty line */
5413 if (!**args)
5414 continue;
5415
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005416 if (*line) {
5417 /* we had to stop due to too many args.
5418 * Let's terminate the string, print the offending part then cut the
5419 * last arg.
5420 */
5421 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5422 line++;
5423 *line = '\0';
5424
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005425 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005426 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005427 err_code |= ERR_ALERT | ERR_FATAL;
5428 args[arg] = line;
5429 }
5430
Willy Tarreau540abe42007-05-02 20:50:16 +02005431 /* zero out remaining args and ensure that at least one entry
5432 * is zeroed out.
5433 */
5434 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 args[arg] = line;
5436 }
5437
Willy Tarreau3842f002009-06-14 11:39:52 +02005438 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005439 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005440 char *tmp;
5441
Willy Tarreau3842f002009-06-14 11:39:52 +02005442 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005443 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005444 for (arg=0; *args[arg+1]; arg++)
5445 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005446 *tmp = '\0'; // fix the next arg to \0
5447 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005448 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005449 else if (!strcmp(args[0], "default")) {
5450 kwm = KWM_DEF;
5451 for (arg=0; *args[arg+1]; arg++)
5452 args[arg] = args[arg+1]; // shift args after inversion
5453 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005454
William Lallemand0f99e342011-10-12 17:50:54 +02005455 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5456 strcmp(args[0], "log") != 0) {
5457 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005458 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005459 }
5460
Willy Tarreau977b8e42006-12-29 14:19:17 +01005461 if (!strcmp(args[0], "listen") ||
5462 !strcmp(args[0], "frontend") ||
5463 !strcmp(args[0], "backend") ||
5464 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005465 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005467 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005468 cursection = strdup(args[0]);
5469 }
5470 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005472 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005473 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005474 }
5475 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005476 confsect = CFG_USERLIST;
5477 free(cursection);
5478 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005479 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005480 else if (!strcmp(args[0], "peers")) {
5481 confsect = CFG_PEERS;
5482 free(cursection);
5483 cursection = strdup(args[0]);
5484 }
5485
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 /* else it's a section keyword */
5487
5488 switch (confsect) {
5489 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005490 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 break;
5492 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005493 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005494 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005495 case CFG_USERLIST:
5496 err_code |= cfg_parse_users(file, linenum, args, kwm);
5497 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005498 case CFG_PEERS:
5499 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5500 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005502 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005503 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005505
5506 if (err_code & ERR_ABORT)
5507 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005509 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005510 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005512 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005513}
5514
Willy Tarreaubb925012009-07-23 13:36:36 +02005515/*
5516 * Returns the error code, 0 if OK, or any combination of :
5517 * - ERR_ABORT: must abort ASAP
5518 * - ERR_FATAL: we can continue parsing but not start the service
5519 * - ERR_WARN: a warning has been emitted
5520 * - ERR_ALERT: an alert has been emitted
5521 * Only the two first ones can stop processing, the two others are just
5522 * indicators.
5523 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005524int check_config_validity()
5525{
5526 int cfgerr = 0;
5527 struct proxy *curproxy = NULL;
5528 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005529 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005530 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005531 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532
5533 /*
5534 * Now, check for the integrity of all that we have collected.
5535 */
5536
5537 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005538 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005540 /* first, we will invert the proxy list order */
5541 curproxy = NULL;
5542 while (proxy) {
5543 struct proxy *next;
5544
5545 next = proxy->next;
5546 proxy->next = curproxy;
5547 curproxy = proxy;
5548 if (!next)
5549 break;
5550 proxy = next;
5551 }
5552
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005554 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005555 err_code |= ERR_ALERT | ERR_FATAL;
5556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 }
5558
5559 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005560 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005561 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005562 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005563 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005564 unsigned int next_id;
5565
5566 if (!curproxy->uuid) {
5567 /* proxy ID not set, use automatic numbering with first
5568 * spare entry starting with next_pxid.
5569 */
5570 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5571 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5572 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005573 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005574 next_pxid++;
5575
Willy Tarreau55ea7572007-06-17 19:56:27 +02005576
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005578 /* ensure we don't keep listeners uselessly bound */
5579 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 curproxy = curproxy->next;
5581 continue;
5582 }
5583
Willy Tarreauff01a212009-03-15 13:46:16 +01005584 switch (curproxy->mode) {
5585 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005586 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005587 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005588 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5589 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005590 cfgerr++;
5591 }
5592
5593 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005594 Warning("config : servers will be ignored for %s '%s'.\n",
5595 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005596 break;
5597
5598 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005599 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005600 break;
5601
5602 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005603 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005604 break;
5605 }
5606
5607 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005608 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5609 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 cfgerr++;
5611 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005612
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005613 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005614 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005615 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005616 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5617 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 cfgerr++;
5619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005621 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005622 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5623 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005624 cfgerr++;
5625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005627 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005628 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5629 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005630 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005631 }
5632 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005633 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005634 /* If no LB algo is set in a backend, and we're not in
5635 * transparent mode, dispatch mode nor proxy mode, we
5636 * want to use balance roundrobin by default.
5637 */
5638 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5639 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 }
5641 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005642
Willy Tarreau1620ec32011-08-06 17:05:02 +02005643 if (curproxy->options & PR_O_DISPATCH)
5644 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5645 else if (curproxy->options & PR_O_HTTP_PROXY)
5646 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5647 else if (curproxy->options & PR_O_TRANSP)
5648 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005649
Willy Tarreau1620ec32011-08-06 17:05:02 +02005650 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5651 if (curproxy->options & PR_O_DISABLE404) {
5652 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5653 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5654 err_code |= ERR_WARN;
5655 curproxy->options &= ~PR_O_DISABLE404;
5656 }
5657 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5658 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5659 "send-state", proxy_type_str(curproxy), curproxy->id);
5660 err_code |= ERR_WARN;
5661 curproxy->options &= ~PR_O2_CHK_SNDST;
5662 }
Willy Tarreauef781042010-01-27 11:53:01 +01005663 }
5664
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005665 /* if a default backend was specified, let's find it */
5666 if (curproxy->defbe.name) {
5667 struct proxy *target;
5668
Alex Williams96532db2009-11-01 21:27:13 -05005669 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005670 if (!target) {
5671 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5672 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005673 cfgerr++;
5674 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005675 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5676 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005677 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005678 } else {
5679 free(curproxy->defbe.name);
5680 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005681 /* we force the backend to be present on at least all of
5682 * the frontend's processes.
5683 */
5684 target->bind_proc = curproxy->bind_proc ?
5685 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 }
5687 }
5688
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005689 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005690 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5691 /* map jump target for ACT_SETBE in req_rep chain */
5692 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005693 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005694 struct proxy *target;
5695
Willy Tarreaua496b602006-12-17 23:15:24 +01005696 if (exp->action != ACT_SETBE)
5697 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005698
Alex Williams96532db2009-11-01 21:27:13 -05005699 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005700 if (!target) {
5701 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5702 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005703 cfgerr++;
5704 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005705 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5706 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005707 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005708 } else {
5709 free((void *)exp->replace);
5710 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005711 /* we force the backend to be present on at least all of
5712 * the frontend's processes.
5713 */
5714 target->bind_proc = curproxy->bind_proc ?
5715 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005716 }
5717 }
5718 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005719
5720 /* find the target proxy for 'use_backend' rules */
5721 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005722 struct proxy *target;
5723
Alex Williams96532db2009-11-01 21:27:13 -05005724 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005725
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005726 if (!target) {
5727 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5728 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005729 cfgerr++;
5730 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005731 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5732 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005733 cfgerr++;
5734 } else {
5735 free((void *)rule->be.name);
5736 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005737 /* we force the backend to be present on at least all of
5738 * the frontend's processes.
5739 */
5740 target->bind_proc = curproxy->bind_proc ?
5741 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005742 }
5743 }
5744
Emeric Brunb982a3d2010-01-04 15:45:53 +01005745 /* find the target table for 'stick' rules */
5746 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5747 struct proxy *target;
5748
Emeric Brun1d33b292010-01-04 15:47:17 +01005749 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5750 if (mrule->flags & STK_IS_STORE)
5751 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5752
Emeric Brunb982a3d2010-01-04 15:45:53 +01005753 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005754 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005755 else
5756 target = curproxy;
5757
5758 if (!target) {
5759 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5760 curproxy->id, mrule->table.name);
5761 cfgerr++;
5762 }
5763 else if (target->table.size == 0) {
5764 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5765 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5766 cfgerr++;
5767 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005768 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005769 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5770 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5771 cfgerr++;
5772 }
5773 else {
5774 free((void *)mrule->table.name);
5775 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005776 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 }
5778 }
5779
5780 /* find the target table for 'store response' rules */
5781 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5782 struct proxy *target;
5783
Emeric Brun1d33b292010-01-04 15:47:17 +01005784 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5785
Emeric Brunb982a3d2010-01-04 15:45:53 +01005786 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005787 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005788 else
5789 target = curproxy;
5790
5791 if (!target) {
5792 Alert("Proxy '%s': unable to find store table '%s'.\n",
5793 curproxy->id, mrule->table.name);
5794 cfgerr++;
5795 }
5796 else if (target->table.size == 0) {
5797 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5798 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5799 cfgerr++;
5800 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005801 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005802 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5803 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5804 cfgerr++;
5805 }
5806 else {
5807 free((void *)mrule->table.name);
5808 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005809 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005810 }
5811 }
5812
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005813 /* find the target table for 'tcp-request' layer 4 rules */
5814 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5815 struct proxy *target;
5816
Willy Tarreau56123282010-08-06 19:06:56 +02005817 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005818 continue;
5819
5820 if (trule->act_prm.trk_ctr.table.n)
5821 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5822 else
5823 target = curproxy;
5824
5825 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005826 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5827 curproxy->id, trule->act_prm.trk_ctr.table.n,
5828 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005829 cfgerr++;
5830 }
5831 else if (target->table.size == 0) {
5832 Alert("Proxy '%s': table '%s' used but not configured.\n",
5833 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5834 cfgerr++;
5835 }
5836 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005837 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 +02005838 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5839 cfgerr++;
5840 }
5841 else {
5842 free(trule->act_prm.trk_ctr.table.n);
5843 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005844 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005845 * to pass a list of counters to track and allocate them right here using
5846 * stktable_alloc_data_type().
5847 */
5848 }
5849 }
5850
Willy Tarreaud1f96522010-08-03 19:34:32 +02005851 /* find the target table for 'tcp-request' layer 6 rules */
5852 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5853 struct proxy *target;
5854
Willy Tarreau56123282010-08-06 19:06:56 +02005855 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005856 continue;
5857
5858 if (trule->act_prm.trk_ctr.table.n)
5859 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5860 else
5861 target = curproxy;
5862
5863 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005864 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5865 curproxy->id, trule->act_prm.trk_ctr.table.n,
5866 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005867 cfgerr++;
5868 }
5869 else if (target->table.size == 0) {
5870 Alert("Proxy '%s': table '%s' used but not configured.\n",
5871 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5872 cfgerr++;
5873 }
5874 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005875 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 +02005876 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5877 cfgerr++;
5878 }
5879 else {
5880 free(trule->act_prm.trk_ctr.table.n);
5881 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005882 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005883 * to pass a list of counters to track and allocate them right here using
5884 * stktable_alloc_data_type().
5885 */
5886 }
5887 }
5888
Emeric Brun32da3c42010-09-23 18:39:19 +02005889 if (curproxy->table.peers.name) {
5890 struct peers *curpeers = peers;
5891
5892 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5893 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5894 free((void *)curproxy->table.peers.name);
5895 curproxy->table.peers.p = peers;
5896 break;
5897 }
5898 }
5899
5900 if (!curpeers) {
5901 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5902 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005903 free((void *)curproxy->table.peers.name);
5904 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005905 cfgerr++;
5906 }
5907 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005908 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5909 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005910 free((void *)curproxy->table.peers.name);
5911 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005912 cfgerr++;
5913 }
5914 }
5915
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005916 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005917 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005918 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5919 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5920 "proxy", curproxy->id);
5921 cfgerr++;
5922 goto out_uri_auth_compat;
5923 }
5924
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005925 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005926 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005927 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005928 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005929
Willy Tarreau95fa4692010-02-01 13:05:50 +01005930 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5931 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005932
5933 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005934 uri_auth_compat_req[i++] = "realm";
5935 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5936 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005937
Willy Tarreau95fa4692010-02-01 13:05:50 +01005938 uri_auth_compat_req[i++] = "unless";
5939 uri_auth_compat_req[i++] = "{";
5940 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5941 uri_auth_compat_req[i++] = "}";
5942 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005943
Willy Tarreauff011f22011-01-06 17:51:27 +01005944 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5945 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005946 cfgerr++;
5947 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005948 }
5949
Willy Tarreauff011f22011-01-06 17:51:27 +01005950 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005951
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005952 if (curproxy->uri_auth->auth_realm) {
5953 free(curproxy->uri_auth->auth_realm);
5954 curproxy->uri_auth->auth_realm = NULL;
5955 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005956
5957 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005958 }
5959out_uri_auth_compat:
5960
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005961 cfgerr += acl_find_targets(curproxy);
5962
Willy Tarreau2738a142006-07-08 17:28:09 +02005963 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005964 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005965 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005966 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005967 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005968 " | While not properly invalid, you will certainly encounter various problems\n"
5969 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005970 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005971 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005972 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005973 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005974
Willy Tarreau1fa31262007-12-03 00:36:16 +01005975 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5976 * We must still support older configurations, so let's find out whether those
5977 * parameters have been set or must be copied from contimeouts.
5978 */
5979 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005980 if (!curproxy->timeout.tarpit ||
5981 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005982 /* tarpit timeout not set. We search in the following order:
5983 * default.tarpit, curr.connect, default.connect.
5984 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005985 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005986 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005987 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005988 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005989 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005990 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005991 }
5992 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005993 (!curproxy->timeout.queue ||
5994 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005995 /* queue timeout not set. We search in the following order:
5996 * default.queue, curr.connect, default.connect.
5997 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005998 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005999 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006000 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006001 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006002 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006003 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006004 }
6005 }
6006
Willy Tarreau1620ec32011-08-06 17:05:02 +02006007 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006008 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6009 curproxy->check_req = (char *)malloc(curproxy->check_len);
6010 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006011 }
6012
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006013 /* The small pools required for the capture lists */
6014 if (curproxy->nb_req_cap)
6015 curproxy->req_cap_pool = create_pool("ptrcap",
6016 curproxy->nb_req_cap * sizeof(char *),
6017 MEM_F_SHARED);
6018 if (curproxy->nb_rsp_cap)
6019 curproxy->rsp_cap_pool = create_pool("ptrcap",
6020 curproxy->nb_rsp_cap * sizeof(char *),
6021 MEM_F_SHARED);
6022
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023 /* first, we will invert the servers list order */
6024 newsrv = NULL;
6025 while (curproxy->srv) {
6026 struct server *next;
6027
6028 next = curproxy->srv->next;
6029 curproxy->srv->next = newsrv;
6030 newsrv = curproxy->srv;
6031 if (!next)
6032 break;
6033 curproxy->srv = next;
6034 }
6035
Willy Tarreaudd701652010-05-25 23:03:02 +02006036 /* assign automatic UIDs to servers which don't have one yet */
6037 next_id = 1;
6038 newsrv = curproxy->srv;
6039 while (newsrv != NULL) {
6040 if (!newsrv->puid) {
6041 /* server ID not set, use automatic numbering with first
6042 * spare entry starting with next_svid.
6043 */
6044 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6045 newsrv->conf.id.key = newsrv->puid = next_id;
6046 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6047 }
6048 next_id++;
6049 newsrv = newsrv->next;
6050 }
6051
Willy Tarreau20697042007-11-15 23:26:18 +01006052 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006053 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006055 /* We have to initialize the server lookup mechanism depending
6056 * on what LB algorithm was choosen.
6057 */
6058
6059 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6060 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6061 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006062 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6063 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6064 init_server_map(curproxy);
6065 } else {
6066 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6067 fwrr_init_server_groups(curproxy);
6068 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006069 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006070
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006071 case BE_LB_KIND_LC:
6072 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006073 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006074 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006075
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006076 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006077 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6078 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6079 chash_init_server_tree(curproxy);
6080 } else {
6081 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6082 init_server_map(curproxy);
6083 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006084 break;
6085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006086
6087 if (curproxy->options & PR_O_LOGASAP)
6088 curproxy->to_log &= ~LW_BYTES;
6089
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006090 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006091 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006092 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6093 proxy_type_str(curproxy), curproxy->id);
6094 err_code |= ERR_WARN;
6095 }
6096
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006097 if (curproxy->mode != PR_MODE_HTTP) {
6098 int optnum;
6099
6100 if (curproxy->options & PR_O_COOK_ANY) {
6101 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6102 proxy_type_str(curproxy), curproxy->id);
6103 err_code |= ERR_WARN;
6104 }
6105
6106 if (curproxy->uri_auth) {
6107 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6108 proxy_type_str(curproxy), curproxy->id);
6109 err_code |= ERR_WARN;
6110 curproxy->uri_auth = NULL;
6111 }
6112
Willy Tarreau87cf5142011-08-19 22:57:24 +02006113 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006114 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6115 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6116 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006117 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006118 }
6119
6120 if (curproxy->options & PR_O_ORGTO) {
6121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6122 "originalto", proxy_type_str(curproxy), curproxy->id);
6123 err_code |= ERR_WARN;
6124 curproxy->options &= ~PR_O_ORGTO;
6125 }
6126
6127 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6128 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6129 (curproxy->cap & cfg_opts[optnum].cap) &&
6130 (curproxy->options & cfg_opts[optnum].val)) {
6131 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6132 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6133 err_code |= ERR_WARN;
6134 curproxy->options &= ~cfg_opts[optnum].val;
6135 }
6136 }
6137
6138 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6139 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6140 (curproxy->cap & cfg_opts2[optnum].cap) &&
6141 (curproxy->options2 & cfg_opts2[optnum].val)) {
6142 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6143 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6144 err_code |= ERR_WARN;
6145 curproxy->options2 &= ~cfg_opts2[optnum].val;
6146 }
6147 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006148
Willy Tarreauefa5f512010-03-30 20:13:29 +02006149#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006150 if (curproxy->bind_hdr_occ) {
6151 curproxy->bind_hdr_occ = 0;
6152 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6153 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6154 err_code |= ERR_WARN;
6155 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006156#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006157 }
6158
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006160 * ensure that we're not cross-dressing a TCP server into HTTP.
6161 */
6162 newsrv = curproxy->srv;
6163 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006164 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006165 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6166 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006167 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006168 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006169
Willy Tarreau0cec3312011-10-31 13:49:26 +01006170 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6171 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6172 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6173 err_code |= ERR_WARN;
6174 }
6175
Willy Tarreauefa5f512010-03-30 20:13:29 +02006176#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006177 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6178 newsrv->bind_hdr_occ = 0;
6179 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6180 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6181 err_code |= ERR_WARN;
6182 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006183#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006184 newsrv = newsrv->next;
6185 }
6186
6187 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 * If this server supports a maxconn parameter, it needs a dedicated
6189 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006190 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006191 */
6192 newsrv = curproxy->srv;
6193 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006194 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006195 /* Only 'minconn' was specified, or it was higher than or equal
6196 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6197 * this will avoid further useless expensive computations.
6198 */
6199 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006200 } else if (newsrv->maxconn && !newsrv->minconn) {
6201 /* minconn was not specified, so we set it to maxconn */
6202 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 }
6204
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006205 if (newsrv->trackit) {
6206 struct proxy *px;
6207 struct server *srv;
6208 char *pname, *sname;
6209
6210 pname = newsrv->trackit;
6211 sname = strrchr(pname, '/');
6212
6213 if (sname)
6214 *sname++ = '\0';
6215 else {
6216 sname = pname;
6217 pname = NULL;
6218 }
6219
6220 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006221 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006222 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006223 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6224 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006225 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006226 cfgerr++;
6227 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006228 }
6229 } else
6230 px = curproxy;
6231
6232 srv = findserver(px, sname);
6233 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006234 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6235 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006236 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006237 cfgerr++;
6238 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006239 }
6240
6241 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006242 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006243 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006244 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006245 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006246 cfgerr++;
6247 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006248 }
6249
6250 if (curproxy != px &&
6251 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006252 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006253 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006254 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006255 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006256 cfgerr++;
6257 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006258 }
6259
Willy Tarreau44267702011-10-28 15:35:33 +02006260 newsrv->track = srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006261 newsrv->tracknext = srv->tracknext;
6262 srv->tracknext = newsrv;
6263
6264 free(newsrv->trackit);
6265 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006266 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 newsrv = newsrv->next;
6268 }
6269
Willy Tarreauc1a21672009-08-16 22:37:44 +02006270 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006271 curproxy->accept = frontend_accept;
6272
Willy Tarreauc1a21672009-08-16 22:37:44 +02006273 if (curproxy->tcp_req.inspect_delay ||
6274 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006275 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006276
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006277 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006278 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006279 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006280 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006281
6282 /* both TCP and HTTP must check switching rules */
6283 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6284 }
6285
6286 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006287 if (curproxy->tcp_req.inspect_delay ||
6288 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6289 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6290
Emeric Brun97679e72010-09-23 17:56:44 +02006291 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6292 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6293
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006294 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006295 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006296 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006297 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006298
6299 /* If the backend does requires RDP cookie persistence, we have to
6300 * enable the corresponding analyser.
6301 */
6302 if (curproxy->options2 & PR_O2_RDPC_PRST)
6303 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6304 }
6305
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006306 listener = NULL;
6307 while (curproxy->listen) {
6308 struct listener *next;
6309
6310 next = curproxy->listen->next;
6311 curproxy->listen->next = listener;
6312 listener = curproxy->listen;
6313
6314 if (!next)
6315 break;
6316
6317 curproxy->listen = next;
6318 }
6319
Willy Tarreaue6b98942007-10-29 01:09:36 +01006320 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006321 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006322 listener = curproxy->listen;
6323 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006324 if (!listener->luid) {
6325 /* listener ID not set, use automatic numbering with first
6326 * spare entry starting with next_luid.
6327 */
6328 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6329 listener->conf.id.key = listener->luid = next_id;
6330 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006331 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006332 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006333
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006334 /* enable separate counters */
6335 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6336 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6337 if (!listener->name) {
6338 sprintf(trash, "sock-%d", listener->luid);
6339 listener->name = strdup(trash);
6340 }
6341 }
6342
Willy Tarreaue6b98942007-10-29 01:09:36 +01006343 if (curproxy->options & PR_O_TCP_NOLING)
6344 listener->options |= LI_O_NOLINGER;
6345 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006346 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006347 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006348 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006349 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006350 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006351 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006352
Willy Tarreau8a956912010-10-15 14:27:08 +02006353 if (listener->options & LI_O_ACC_PROXY)
6354 listener->analysers |= AN_REQ_DECODE_PROXY;
6355
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006356 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6357 listener->options |= LI_O_TCP_RULES;
6358
Willy Tarreaude3041d2010-05-31 10:56:17 +02006359 if (curproxy->mon_mask.s_addr)
6360 listener->options |= LI_O_CHK_MONNET;
6361
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006362 /* smart accept mode is automatic in HTTP mode */
6363 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6364 (curproxy->mode == PR_MODE_HTTP &&
6365 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6366 listener->options |= LI_O_NOQUICKACK;
6367
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006368 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006369 listener = listener->next;
6370 }
6371
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006372 /* Check multi-process mode compatibility for the current proxy */
6373 if (global.nbproc > 1) {
6374 int nbproc = 0;
6375 if (curproxy->bind_proc) {
6376 int proc;
6377 for (proc = 0; proc < global.nbproc; proc++) {
6378 if (curproxy->bind_proc & (1 << proc)) {
6379 nbproc++;
6380 }
6381 }
6382 } else {
6383 nbproc = global.nbproc;
6384 }
6385 if (curproxy->table.peers.name) {
6386 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6387 curproxy->id);
6388 cfgerr++;
6389 }
6390 if (nbproc > 1) {
6391 if (curproxy->uri_auth) {
6392 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6393 curproxy->id);
6394 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6395 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6396 curproxy->id);
6397 }
6398 }
6399 if (curproxy->appsession_name) {
6400 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6401 curproxy->id);
6402 }
6403 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6404 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6405 curproxy->id);
6406 }
6407 }
6408 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006409
6410 /* create the task associated with the proxy */
6411 curproxy->task = task_new();
6412 if (curproxy->task) {
6413 curproxy->task->context = curproxy;
6414 curproxy->task->process = manage_proxy;
6415 /* no need to queue, it will be done automatically if some
6416 * listener gets limited.
6417 */
6418 curproxy->task->expire = TICK_ETERNITY;
6419 } else {
6420 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6421 curproxy->id);
6422 cfgerr++;
6423 }
6424
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 curproxy = curproxy->next;
6426 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006427
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006428 /* Check multi-process mode compatibility */
6429 if (global.nbproc > 1) {
6430 if (global.stats_fe) {
6431 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6432 }
6433 }
6434
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006435 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6436 struct auth_users *curuser;
6437 int g;
6438
6439 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6440 unsigned int group_mask = 0;
6441 char *group = NULL;
6442
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006443 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006444 continue;
6445
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006446 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006447
6448 for (g = 0; g < curuserlist->grpcnt; g++)
6449 if (!strcmp(curuserlist->groups[g], group))
6450 break;
6451
6452 if (g == curuserlist->grpcnt) {
6453 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6454 curuserlist->name, group, curuser->user);
6455 err_code |= ERR_ALERT | ERR_FATAL;
6456 goto out;
6457 }
6458
6459 group_mask |= (1 << g);
6460 }
6461
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006462 free(curuser->u.groups);
6463 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006464 }
6465
6466 for (g = 0; g < curuserlist->grpcnt; g++) {
6467 char *user = NULL;
6468
6469 if (!curuserlist->groupusers[g])
6470 continue;
6471
6472 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6473 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6474 if (!strcmp(curuser->user, user))
6475 break;
6476
6477 if (!curuser) {
6478 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6479 curuserlist->name, user, curuserlist->groups[g]);
6480 err_code |= ERR_ALERT | ERR_FATAL;
6481 goto out;
6482 }
6483
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006484 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006485 }
6486
6487 free(curuserlist->groupusers[g]);
6488 }
6489
6490 free(curuserlist->groupusers);
6491
6492#ifdef DEBUG_AUTH
6493 for (g = 0; g < curuserlist->grpcnt; g++) {
6494 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6495
6496 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6497 if (curuser->group_mask & (1 << g))
6498 fprintf(stderr, " %s", curuser->user);
6499 }
6500
6501 fprintf(stderr, "\n");
6502 }
6503#endif
6504
Willy Tarreaufbb78422011-06-05 15:38:35 +02006505 }
6506
6507 /* automatically compute fullconn if not set. We must not do it in the
6508 * loop above because cross-references are not yet fully resolved.
6509 */
6510 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6511 /* If <fullconn> is not set, let's set it to 10% of the sum of
6512 * the possible incoming frontend's maxconns.
6513 */
6514 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6515 struct proxy *fe;
6516 int total = 0;
6517
6518 /* sum up the number of maxconns of frontends which
6519 * reference this backend at least once or which are
6520 * the same one ('listen').
6521 */
6522 for (fe = proxy; fe; fe = fe->next) {
6523 struct switching_rule *rule;
6524 struct hdr_exp *exp;
6525 int found = 0;
6526
6527 if (!(fe->cap & PR_CAP_FE))
6528 continue;
6529
6530 if (fe == curproxy) /* we're on a "listen" instance */
6531 found = 1;
6532
6533 if (fe->defbe.be == curproxy) /* "default_backend" */
6534 found = 1;
6535
6536 /* check if a "use_backend" rule matches */
6537 if (!found) {
6538 list_for_each_entry(rule, &fe->switching_rules, list) {
6539 if (rule->be.backend == curproxy) {
6540 found = 1;
6541 break;
6542 }
6543 }
6544 }
6545
6546 /* check if a "reqsetbe" rule matches */
6547 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6548 if (exp->action == ACT_SETBE &&
6549 (struct proxy *)exp->replace == curproxy) {
6550 found = 1;
6551 break;
6552 }
6553 }
6554
6555 /* now we've checked all possible ways to reference a backend
6556 * from a frontend.
6557 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006558 if (!found)
6559 continue;
6560 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006561 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006562 /* we have the sum of the maxconns in <total>. We only
6563 * keep 10% of that sum to set the default fullconn, with
6564 * a hard minimum of 1 (to avoid a divide by zero).
6565 */
6566 curproxy->fullconn = (total + 9) / 10;
6567 if (!curproxy->fullconn)
6568 curproxy->fullconn = 1;
6569 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006570 }
6571
Willy Tarreau056f5682010-06-06 15:51:11 +02006572 /* initialize stick-tables on backend capable proxies. This must not
6573 * be done earlier because the data size may be discovered while parsing
6574 * other proxies.
6575 */
6576 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006577 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006578
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006579 /*
6580 * Recount currently required checks.
6581 */
6582
6583 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6584 int optnum;
6585
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006586 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6587 if (curproxy->options & cfg_opts[optnum].val)
6588 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006589
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006590 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6591 if (curproxy->options2 & cfg_opts2[optnum].val)
6592 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006593 }
6594
Willy Tarreau122541c2011-09-07 21:24:49 +02006595 if (peers) {
6596 struct peers *curpeers = peers, **last;
6597 struct peer *p, *pb;
6598
6599 /* Remove all peers sections which don't have a valid listener.
6600 * This can happen when a peers section is never referenced and
6601 * does not contain a local peer.
6602 */
6603 last = &peers;
6604 while (*last) {
6605 curpeers = *last;
6606 if (curpeers->peers_fe) {
6607 last = &curpeers->next;
6608 continue;
6609 }
6610
6611 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6612 curpeers->id, localpeer);
6613
6614 p = curpeers->remote;
6615 while (p) {
6616 pb = p->next;
6617 free(p->id);
6618 free(p);
6619 p = pb;
6620 }
6621
6622 /* Destroy and unlink this curpeers section.
6623 * Note: curpeers is backed up into *last.
6624 */
6625 free(curpeers->id);
6626 curpeers = curpeers->next;
6627 free(*last);
6628 *last = curpeers;
6629 }
6630 }
6631
Willy Tarreauac1932d2011-10-24 19:14:41 +02006632 if (!global.tune.max_http_hdr)
6633 global.tune.max_http_hdr = MAX_HTTP_HDR;
6634
Willy Tarreau34eb6712011-10-24 18:15:04 +02006635 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006636 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006637 MEM_F_SHARED);
6638
Willy Tarreaubb925012009-07-23 13:36:36 +02006639 if (cfgerr > 0)
6640 err_code |= ERR_ALERT | ERR_FATAL;
6641 out:
6642 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006643}
6644
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006645/*
6646 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6647 * parsing sessions.
6648 */
6649void cfg_register_keywords(struct cfg_kw_list *kwl)
6650{
6651 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6652}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006653
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006654/*
6655 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6656 */
6657void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6658{
6659 LIST_DEL(&kwl->list);
6660 LIST_INIT(&kwl->list);
6661}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006662
6663/*
6664 * Local variables:
6665 * c-indent-level: 8
6666 * c-basic-offset: 8
6667 * End:
6668 */