blob: dac6bcab5ea31b5afb97e3bb4437d4a97840968e [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 Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "uid")) {
600 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200601 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200602 err_code |= ERR_ALERT;
603 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 }
605 if (*(args[1]) == 0) {
606 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 }
610 global.uid = atol(args[1]);
611 }
612 else if (!strcmp(args[0], "gid")) {
613 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200614 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623 global.gid = atol(args[1]);
624 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200625 /* user/group name handling */
626 else if (!strcmp(args[0], "user")) {
627 struct passwd *ha_user;
628 if (global.uid != 0) {
629 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT;
631 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 errno = 0;
634 ha_user = getpwnam(args[1]);
635 if (ha_user != NULL) {
636 global.uid = (int)ha_user->pw_uid;
637 }
638 else {
639 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 +0200640 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 }
642 }
643 else if (!strcmp(args[0], "group")) {
644 struct group *ha_group;
645 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200646 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200647 err_code |= ERR_ALERT;
648 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 errno = 0;
651 ha_group = getgrnam(args[1]);
652 if (ha_group != NULL) {
653 global.gid = (int)ha_group->gr_gid;
654 }
655 else {
656 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 +0200657 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200658 }
659 }
660 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 else if (!strcmp(args[0], "nbproc")) {
662 if (global.nbproc != 0) {
663 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200664 err_code |= ERR_ALERT;
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 }
667 if (*(args[1]) == 0) {
668 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200669 err_code |= ERR_ALERT | ERR_FATAL;
670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200671 }
672 global.nbproc = atol(args[1]);
673 }
674 else if (!strcmp(args[0], "maxconn")) {
675 if (global.maxconn != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200684 }
685 global.maxconn = atol(args[1]);
686#ifdef SYSTEM_MAXCONN
687 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
688 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);
689 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200691 }
692#endif /* SYSTEM_MAXCONN */
693 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200694 else if (!strcmp(args[0], "maxconnrate")) {
695 if (global.cps_lim != 0) {
696 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
697 err_code |= ERR_ALERT;
698 goto out;
699 }
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.cps_lim = atol(args[1]);
706 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100707 else if (!strcmp(args[0], "maxpipes")) {
708 if (global.maxpipes != 0) {
709 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200710 err_code |= ERR_ALERT;
711 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100712 }
713 if (*(args[1]) == 0) {
714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100717 }
718 global.maxpipes = atol(args[1]);
719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 else if (!strcmp(args[0], "ulimit-n")) {
721 if (global.rlimit_nofile != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT;
724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200730 }
731 global.rlimit_nofile = atol(args[1]);
732 }
733 else if (!strcmp(args[0], "chroot")) {
734 if (global.chroot != NULL) {
735 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT;
737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200743 }
744 global.chroot = strdup(args[1]);
745 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200746 else if (!strcmp(args[0], "description")) {
747 int i, len=0;
748 char *d;
749
750 if (!*args[1]) {
751 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
752 file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756
757 for(i=1; *args[i]; i++)
758 len += strlen(args[i])+1;
759
760 if (global.desc)
761 free(global.desc);
762
763 global.desc = d = (char *)calloc(1, len);
764
765 d += sprintf(d, "%s", args[1]);
766 for(i=2; *args[i]; i++)
767 d += sprintf(d, " %s", args[i]);
768 }
769 else if (!strcmp(args[0], "node")) {
770 int i;
771 char c;
772
773 for (i=0; args[1][i]; i++) {
774 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100775 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
776 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200777 break;
778 }
779
780 if (!i || args[1][i]) {
781 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
782 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
783 file, linenum, args[0]);
784 err_code |= ERR_ALERT | ERR_FATAL;
785 goto out;
786 }
787
788 if (global.node)
789 free(global.node);
790
791 global.node = strdup(args[1]);
792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200793 else if (!strcmp(args[0], "pidfile")) {
794 if (global.pidfile != NULL) {
795 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200796 err_code |= ERR_ALERT;
797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200798 }
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 }
804 global.pidfile = strdup(args[1]);
805 }
Emeric Bruned760922010-10-22 17:59:25 +0200806 else if (!strcmp(args[0], "unix-bind")) {
807 int cur_arg = 1;
808 while (*(args[cur_arg])) {
809 if (!strcmp(args[cur_arg], "prefix")) {
810 if (global.unix_bind.prefix != NULL) {
811 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
812 err_code |= ERR_ALERT;
813 cur_arg += 2;
814 continue;
815 }
816
817 if (*(args[cur_arg+1]) == 0) {
818 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
819 err_code |= ERR_ALERT | ERR_FATAL;
820 goto out;
821 }
822 global.unix_bind.prefix = strdup(args[cur_arg+1]);
823 cur_arg += 2;
824 continue;
825 }
826
827 if (!strcmp(args[cur_arg], "mode")) {
828
829 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
830 cur_arg += 2;
831 continue;
832 }
833
834 if (!strcmp(args[cur_arg], "uid")) {
835
836 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
837 cur_arg += 2;
838 continue;
839 }
840
841 if (!strcmp(args[cur_arg], "gid")) {
842
843 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
844 cur_arg += 2;
845 continue;
846 }
847
848 if (!strcmp(args[cur_arg], "user")) {
849 struct passwd *user;
850
851 user = getpwnam(args[cur_arg + 1]);
852 if (!user) {
853 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
854 file, linenum, args[0], args[cur_arg + 1 ]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858
859 global.unix_bind.ux.uid = user->pw_uid;
860 cur_arg += 2;
861 continue;
862 }
863
864 if (!strcmp(args[cur_arg], "group")) {
865 struct group *group;
866
867 group = getgrnam(args[cur_arg + 1]);
868 if (!group) {
869 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
870 file, linenum, args[0], args[cur_arg + 1 ]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874
875 global.unix_bind.ux.gid = group->gr_gid;
876 cur_arg += 2;
877 continue;
878 }
879
Willy Tarreaub48f9582011-09-05 01:17:06 +0200880 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200881 file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100887 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200888 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889
890 if (*(args[1]) == 0 || *(args[2]) == 0) {
891 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200892 err_code |= ERR_ALERT | ERR_FATAL;
893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894 }
895
896 facility = get_log_facility(args[2]);
897 if (facility < 0) {
898 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200899 err_code |= ERR_ALERT | ERR_FATAL;
900 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901 }
902
903 level = 7; /* max syslog level = debug */
904 if (*(args[3])) {
905 level = get_log_level(args[3]);
906 if (level < 0) {
907 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT | ERR_FATAL;
909 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 }
912
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200913 minlvl = 0; /* limit syslog level to this level (emerg) */
914 if (*(args[4])) {
915 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200917 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200918 err_code |= ERR_ALERT | ERR_FATAL;
919 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200920 }
921 }
922
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100924 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100925 if (!sk) {
926 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100927 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100931 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100932 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100933 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100934 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100935 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100939 logsrv.addr = *sk;
940 if (!get_host_port(&logsrv.addr))
941 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943
944 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100945 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946 global.logfac1 = facility;
947 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200948 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100951 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 global.logfac2 = facility;
953 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200954 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 }
956 else {
957 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200960 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100961 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
962 char *name;
963 int len;
964
965 if (global.log_send_hostname != NULL) {
966 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
967 err_code |= ERR_ALERT;
968 goto out;
969 }
970
971 if (*(args[1]))
972 name = args[1];
973 else
974 name = hostname;
975
976 len = strlen(name);
977
978 /* We'll add a space after the name to respect the log format */
979 free(global.log_send_hostname);
980 global.log_send_hostname = malloc(len + 2);
981 snprintf(global.log_send_hostname, len + 2, "%s ", name);
982 }
Kevinm48936af2010-12-22 16:08:21 +0000983 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
984 if (*(args[1]) == 0) {
985 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
986 err_code |= ERR_ALERT | ERR_FATAL;
987 goto out;
988 }
989 free(global.log_tag);
990 global.log_tag = strdup(args[1]);
991 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200992 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
993 if (global.spread_checks != 0) {
994 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT;
996 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200997 }
998 if (*(args[1]) == 0) {
999 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001000 err_code |= ERR_ALERT | ERR_FATAL;
1001 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001002 }
1003 global.spread_checks = atol(args[1]);
1004 if (global.spread_checks < 0 || global.spread_checks > 50) {
1005 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001008 }
1009 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001010 struct cfg_kw_list *kwl;
1011 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001012 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001013
1014 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1015 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1016 if (kwl->kw[index].section != CFG_GLOBAL)
1017 continue;
1018 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1019 /* prepare error message just in case */
1020 snprintf(trash, sizeof(trash),
1021 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001022 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1023 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001024 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001025 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001026 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001027 else if (rc > 0) {
1028 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001029 err_code |= ERR_WARN;
1030 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001031 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001032 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001033 }
1034 }
1035 }
1036
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001038 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001039 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001040
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 out:
1042 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001043}
1044
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001045void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001047 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 defproxy.mode = PR_MODE_TCP;
1049 defproxy.state = PR_STNEW;
1050 defproxy.maxconn = cfg_maxpconn;
1051 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001052
1053 defproxy.defsrv.inter = DEF_CHKINTR;
1054 defproxy.defsrv.fastinter = 0;
1055 defproxy.defsrv.downinter = 0;
1056 defproxy.defsrv.rise = DEF_RISETIME;
1057 defproxy.defsrv.fall = DEF_FALLTIME;
1058 defproxy.defsrv.check_port = 0;
1059 defproxy.defsrv.maxqueue = 0;
1060 defproxy.defsrv.minconn = 0;
1061 defproxy.defsrv.maxconn = 0;
1062 defproxy.defsrv.slowstart = 0;
1063 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1064 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1065 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066}
1067
Willy Tarreauade5ec42010-01-28 19:33:49 +01001068
1069static int create_cond_regex_rule(const char *file, int line,
1070 struct proxy *px, int dir, int action, int flags,
1071 const char *cmd, const char *reg, const char *repl,
1072 const char **cond_start)
1073{
1074 regex_t *preg = NULL;
1075 const char *err;
1076 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001077 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001078
1079 if (px == &defproxy) {
1080 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1081 err_code |= ERR_ALERT | ERR_FATAL;
1082 goto err;
1083 }
1084
1085 if (*reg == 0) {
1086 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1087 err_code |= ERR_ALERT | ERR_FATAL;
1088 goto err;
1089 }
1090
1091 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1092 err_code |= ERR_WARN;
1093
Willy Tarreau5321c422010-01-28 20:35:13 +01001094 if (cond_start &&
1095 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1096 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1097 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1098 file, line, cmd);
1099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto err;
1101 }
1102 }
1103 else if (cond_start && **cond_start) {
1104 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1105 file, line, cmd, *cond_start);
1106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto err;
1108 }
1109
1110 if (dir == ACL_DIR_REQ)
1111 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001112 else
1113 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001114
Willy Tarreauade5ec42010-01-28 19:33:49 +01001115 preg = calloc(1, sizeof(regex_t));
1116 if (!preg) {
1117 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1118 err_code = ERR_ALERT | ERR_FATAL;
1119 goto err;
1120 }
1121
1122 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1123 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1124 err_code = ERR_ALERT | ERR_FATAL;
1125 goto err;
1126 }
1127
1128 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001129 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001130 if (repl && err) {
1131 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1132 file, line, cmd, *err);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto err;
1135 }
1136
1137 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1138 err_code |= ERR_WARN;
1139
1140 return err_code;
1141 err:
1142 free(preg);
1143 return err_code;
1144}
1145
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001147 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001148 * Returns the error code, 0 if OK, or any combination of :
1149 * - ERR_ABORT: must abort ASAP
1150 * - ERR_FATAL: we can continue parsing but not start the service
1151 * - ERR_WARN: a warning has been emitted
1152 * - ERR_ALERT: an alert has been emitted
1153 * Only the two first ones can stop processing, the two others are just
1154 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001156int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1157{
1158 static struct peers *curpeers = NULL;
1159 struct peer *newpeer = NULL;
1160 const char *err;
1161 int err_code = 0;
1162
1163 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1164
1165 err = invalid_char(args[1]);
1166 if (err) {
1167 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1168 file, linenum, *err, args[0], args[1]);
1169 err_code |= ERR_ALERT | ERR_FATAL;
1170 }
1171
1172 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1173 /*
1174 * If there are two proxies with the same name only following
1175 * combinations are allowed:
1176 */
1177 if (strcmp(curpeers->id, args[1]) == 0) {
1178 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1179 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1180 err_code |= ERR_WARN;
1181 }
1182 }
1183
1184 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1185 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1186 err_code |= ERR_ALERT | ERR_ABORT;
1187 goto out;
1188 }
1189
1190 curpeers->next = peers;
1191 peers = curpeers;
1192 curpeers->conf.file = file;
1193 curpeers->conf.line = linenum;
1194 curpeers->last_change = now.tv_sec;
1195 curpeers->id = strdup(args[1]);
1196 }
1197 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1198 char *rport, *raddr;
1199 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001200 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001201
1202 if (!*args[2]) {
1203 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1204 file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207 }
1208
1209 err = invalid_char(args[1]);
1210 if (err) {
1211 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1212 file, linenum, *err, args[1]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216
1217 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1218 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1219 err_code |= ERR_ALERT | ERR_ABORT;
1220 goto out;
1221 }
1222
1223 /* the peers are linked backwards first */
1224 curpeers->count++;
1225 newpeer->next = curpeers->remote;
1226 curpeers->remote = newpeer;
1227 newpeer->peers = curpeers;
1228 newpeer->conf.file = file;
1229 newpeer->conf.line = linenum;
1230
1231 newpeer->last_change = now.tv_sec;
1232 newpeer->id = strdup(args[1]);
1233
1234 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001235 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001236 if (rport) {
1237 *rport++ = 0;
1238 realport = atol(rport);
1239 }
1240 if (!realport) {
1241 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245
Willy Tarreaufab5a432011-03-04 15:31:53 +01001246 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001247 free(raddr);
1248 if (!sk) {
1249 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001254 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001255
1256 if (strcmp(newpeer->id, localpeer) == 0) {
1257 /* Current is local peer, it define a frontend */
1258 newpeer->local = 1;
1259
1260 if (!curpeers->peers_fe) {
1261 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1262 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1263 err_code |= ERR_ALERT | ERR_ABORT;
1264 goto out;
1265 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001266
Willy Tarreau237250c2011-07-29 01:49:03 +02001267 init_new_proxy(curpeers->peers_fe);
1268 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001269
1270 curpeers->peers_fe->last_change = now.tv_sec;
1271 curpeers->peers_fe->id = strdup(args[1]);
1272 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001273 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001274 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1275 curpeers->peers_fe->timeout.connect = 5000;
1276 curpeers->peers_fe->accept = peer_accept;
1277 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001278 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001279 err_code |= ERR_FATAL;
1280 goto out;
1281 }
1282 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1283 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1284 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1285 curpeers->peers_fe->listen->accept = session_accept;
1286 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1287 curpeers->peers_fe->listen->handler = process_session;
1288 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001289 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1290 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001291 }
1292 }
1293 } /* neither "peer" nor "peers" */
1294 else if (*args[0] != 0) {
1295 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299
1300out:
1301 return err_code;
1302}
1303
1304
Willy Tarreau3842f002009-06-14 11:39:52 +02001305int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001306{
1307 static struct proxy *curproxy = NULL;
1308 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001309 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001310 int rc;
1311 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001312 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001313 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001314
Willy Tarreau977b8e42006-12-29 14:19:17 +01001315 if (!strcmp(args[0], "listen"))
1316 rc = PR_CAP_LISTEN;
1317 else if (!strcmp(args[0], "frontend"))
1318 rc = PR_CAP_FE | PR_CAP_RS;
1319 else if (!strcmp(args[0], "backend"))
1320 rc = PR_CAP_BE | PR_CAP_RS;
1321 else if (!strcmp(args[0], "ruleset"))
1322 rc = PR_CAP_RS;
1323 else
1324 rc = PR_CAP_NONE;
1325
1326 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 if (!*args[1]) {
1328 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1329 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1330 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001331 err_code |= ERR_ALERT | ERR_ABORT;
1332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001333 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001334
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001335 err = invalid_char(args[1]);
1336 if (err) {
1337 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1338 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001339 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001340 }
1341
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001342 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1343 /*
1344 * If there are two proxies with the same name only following
1345 * combinations are allowed:
1346 *
1347 * listen backend frontend ruleset
1348 * listen - - - -
1349 * backend - - OK -
1350 * frontend - OK - -
1351 * ruleset - - - -
1352 */
1353
1354 if (!strcmp(curproxy->id, args[1]) &&
1355 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1356 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001357 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1358 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1359 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001361 }
1362 }
1363
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1365 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001366 err_code |= ERR_ALERT | ERR_ABORT;
1367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001368 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001369
Willy Tarreau97cb7802010-01-03 20:23:58 +01001370 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001371 curproxy->next = proxy;
1372 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001373 curproxy->conf.file = file;
1374 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001375 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001377 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378
1379 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001380 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001381 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001382 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001383 err_code |= ERR_FATAL;
1384 goto out;
1385 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001386 new = curproxy->listen;
1387 while (new != last) {
1388 new->conf.file = file;
1389 new->conf.line = linenum;
1390 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001391 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393 }
1394
1395 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001396 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001397 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001398
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001401 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001402 curproxy->no_options = defproxy.no_options;
1403 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001404 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001405 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001406 curproxy->except_net = defproxy.except_net;
1407 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001408 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001409 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001411 if (defproxy.fwdfor_hdr_len) {
1412 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1413 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1414 }
1415
Willy Tarreaub86db342009-11-30 11:50:16 +01001416 if (defproxy.orgto_hdr_len) {
1417 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1418 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1419 }
1420
Willy Tarreau977b8e42006-12-29 14:19:17 +01001421 if (curproxy->cap & PR_CAP_FE) {
1422 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001423 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001424 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001425
1426 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001427 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1428 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001429
1430 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001432
Willy Tarreau977b8e42006-12-29 14:19:17 +01001433 if (curproxy->cap & PR_CAP_BE) {
1434 curproxy->fullconn = defproxy.fullconn;
1435 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001437 if (defproxy.check_req) {
1438 curproxy->check_req = calloc(1, defproxy.check_len);
1439 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1440 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001441 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001442
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001443 if (defproxy.expect_str) {
1444 curproxy->expect_str = strdup(defproxy.expect_str);
1445 if (defproxy.expect_regex) {
1446 /* note: this regex is known to be valid */
1447 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1448 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1449 }
1450 }
1451
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452 if (defproxy.cookie_name)
1453 curproxy->cookie_name = strdup(defproxy.cookie_name);
1454 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001455 if (defproxy.cookie_domain)
1456 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001457
Willy Tarreau31936852010-10-06 16:59:56 +02001458 if (defproxy.cookie_maxidle)
1459 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1460
1461 if (defproxy.cookie_maxlife)
1462 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1463
Emeric Brun647caf12009-06-30 17:57:00 +02001464 if (defproxy.rdp_cookie_name)
1465 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1466 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1467
Willy Tarreau01732802007-11-01 22:48:15 +01001468 if (defproxy.url_param_name)
1469 curproxy->url_param_name = strdup(defproxy.url_param_name);
1470 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001471
Benoitaffb4812009-03-25 13:02:10 +01001472 if (defproxy.hh_name)
1473 curproxy->hh_name = strdup(defproxy.hh_name);
1474 curproxy->hh_len = defproxy.hh_len;
1475 curproxy->hh_match_domain = defproxy.hh_match_domain;
1476
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001477 if (defproxy.iface_name)
1478 curproxy->iface_name = strdup(defproxy.iface_name);
1479 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001482 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001483 if (defproxy.capture_name)
1484 curproxy->capture_name = strdup(defproxy.capture_name);
1485 curproxy->capture_namelen = defproxy.capture_namelen;
1486 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488
Willy Tarreau977b8e42006-12-29 14:19:17 +01001489 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001490 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001491 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001492 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001493 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 curproxy->uri_auth = defproxy.uri_auth;
1495 curproxy->mon_net = defproxy.mon_net;
1496 curproxy->mon_mask = defproxy.mon_mask;
1497 if (defproxy.monitor_uri)
1498 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1499 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001500 if (defproxy.defbe.name)
1501 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502 }
1503
1504 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001505 curproxy->timeout.connect = defproxy.timeout.connect;
1506 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001507 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001508 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001509 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001510 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001511 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 curproxy->source_addr = defproxy.source_addr;
1513 }
1514
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 curproxy->mode = defproxy.mode;
1516 curproxy->logfac1 = defproxy.logfac1;
1517 curproxy->logsrv1 = defproxy.logsrv1;
1518 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001519 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520 curproxy->logfac2 = defproxy.logfac2;
1521 curproxy->logsrv2 = defproxy.logsrv2;
1522 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001523 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001525 curproxy->conf.used_listener_id = EB_ROOT;
1526 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001527
Willy Tarreau93893792009-07-23 13:19:11 +02001528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 }
1530 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1531 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001532 /* FIXME-20070101: we should do this too at the end of the
1533 * config parsing to free all default values.
1534 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001535 free(defproxy.check_req);
1536 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001537 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001538 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001539 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001540 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001541 free(defproxy.capture_name);
1542 free(defproxy.monitor_uri);
1543 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001544 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001545 free(defproxy.fwdfor_hdr_name);
1546 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001547 free(defproxy.orgto_hdr_name);
1548 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001549 free(defproxy.expect_str);
1550 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001551
Willy Tarreaua534fea2008-08-03 12:19:50 +02001552 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001553 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001554
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 /* we cannot free uri_auth because it might already be used */
1556 init_default_instance();
1557 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001558 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 }
1561 else if (curproxy == NULL) {
1562 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001563 err_code |= ERR_ALERT | ERR_FATAL;
1564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 }
1566
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567
1568 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001570 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001571 int cur_arg;
1572
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573 if (curproxy == &defproxy) {
1574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001575 err_code |= ERR_ALERT | ERR_FATAL;
1576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001578 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001579 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580
Emeric Bruned760922010-10-22 17:59:25 +02001581 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001582 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001587
1588 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001589
1590 /* NOTE: the following line might create several listeners if there
1591 * are comma-separated IPs or port ranges. So all further processing
1592 * will have to be applied to all listeners created after last_listen.
1593 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001594 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
1596 goto out;
1597 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001598
Willy Tarreau90a570f2009-10-04 20:54:54 +02001599 new_listen = curproxy->listen;
1600 while (new_listen != last_listen) {
1601 new_listen->conf.file = file;
1602 new_listen->conf.line = linenum;
1603 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001604 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001605 }
1606
Emeric Bruned760922010-10-22 17:59:25 +02001607 /* Set default global rights and owner for unix bind */
1608 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1609 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1610 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001611 cur_arg = 2;
1612 while (*(args[cur_arg])) {
1613 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1614#ifdef SO_BINDTODEVICE
1615 struct listener *l;
1616
Emeric Bruned760922010-10-22 17:59:25 +02001617 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1618 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1619 file, linenum, args[0], args[cur_arg]);
1620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001624 if (!*args[cur_arg + 1]) {
1625 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001629 }
1630
1631 for (l = curproxy->listen; l != last_listen; l = l->next)
1632 l->interface = strdup(args[cur_arg + 1]);
1633
1634 global.last_checks |= LSTCHK_NETADM;
1635
1636 cur_arg += 2;
1637 continue;
1638#else
1639 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1640 file, linenum, args[0], args[cur_arg]);
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#endif
1644 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001645 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1646#ifdef TCP_MAXSEG
1647 struct listener *l;
1648 int mss;
1649
Emeric Bruned760922010-10-22 17:59:25 +02001650 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1651 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1652 file, linenum, args[0], args[cur_arg]);
1653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
1655 }
1656
Willy Tarreaube1b9182009-06-14 18:48:19 +02001657 if (!*args[cur_arg + 1]) {
1658 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001662 }
1663
Willy Tarreau48a7e722010-12-24 15:26:39 +01001664 mss = atoi(args[cur_arg + 1]);
1665 if (!mss || abs(mss) > 65535) {
1666 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001667 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001670 }
1671
1672 for (l = curproxy->listen; l != last_listen; l = l->next)
1673 l->maxseg = mss;
1674
1675 cur_arg += 2;
1676 continue;
1677#else
1678 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1679 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001682#endif
1683 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001684
1685 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1686#ifdef TCP_DEFER_ACCEPT
1687 struct listener *l;
1688
1689 for (l = curproxy->listen; l != last_listen; l = l->next)
1690 l->options |= LI_O_DEF_ACCEPT;
1691
1692 cur_arg ++;
1693 continue;
1694#else
1695 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1696 file, linenum, args[0], args[cur_arg]);
1697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
1699#endif
1700 }
1701
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001702 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001703#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001704 struct listener *l;
1705
Emeric Bruned760922010-10-22 17:59:25 +02001706 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1707 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1708 file, linenum, args[0], args[cur_arg]);
1709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
1711 }
1712
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713 for (l = curproxy->listen; l != last_listen; l = l->next)
1714 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001715
1716 cur_arg ++;
1717 continue;
1718#else
1719 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1720 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001723#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001724 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001725
Willy Tarreau8a956912010-10-15 14:27:08 +02001726 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1727 struct listener *l;
1728
1729 for (l = curproxy->listen; l != last_listen; l = l->next)
1730 l->options |= LI_O_ACC_PROXY;
1731
1732 cur_arg ++;
1733 continue;
1734 }
1735
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001736 if (!strcmp(args[cur_arg], "name")) {
1737 struct listener *l;
1738
1739 for (l = curproxy->listen; l != last_listen; l = l->next)
1740 l->name = strdup(args[cur_arg + 1]);
1741
1742 cur_arg += 2;
1743 continue;
1744 }
1745
1746 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001747 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001748 struct listener *l;
1749
1750 if (curproxy->listen->next != last_listen) {
1751 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1752 file, linenum, args[cur_arg]);
1753 err_code |= ERR_ALERT | ERR_FATAL;
1754 goto out;
1755 }
1756
1757 if (!*args[cur_arg + 1]) {
1758 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1759 file, linenum, args[cur_arg]);
1760 err_code |= ERR_ALERT | ERR_FATAL;
1761 goto out;
1762 }
1763
1764 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001765 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001766
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001767 if (curproxy->listen->luid <= 0) {
1768 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001769 file, linenum);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001774 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1775 if (node) {
1776 l = container_of(node, struct listener, conf.id);
1777 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1778 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1783
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001784 cur_arg += 2;
1785 continue;
1786 }
1787
Emeric Bruned760922010-10-22 17:59:25 +02001788 if (!strcmp(args[cur_arg], "mode")) {
1789
1790 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1791 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1792 file, linenum, args[0], args[cur_arg]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1798
1799 cur_arg += 2;
1800 continue;
1801 }
1802
1803 if (!strcmp(args[cur_arg], "uid")) {
1804
1805 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1806 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1807 file, linenum, args[0], args[cur_arg]);
1808 err_code |= ERR_ALERT | ERR_FATAL;
1809 goto out;
1810 }
1811
1812 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1813 cur_arg += 2;
1814 continue;
1815 }
1816
1817 if (!strcmp(args[cur_arg], "gid")) {
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.gid = atol(args[cur_arg + 1 ]);
1827 cur_arg += 2;
1828 continue;
1829 }
1830
1831 if (!strcmp(args[cur_arg], "user")) {
1832 struct passwd *user;
1833
1834 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1835 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1836 file, linenum, args[0], args[cur_arg]);
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839 }
1840 user = getpwnam(args[cur_arg + 1]);
1841 if (!user) {
1842 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1843 file, linenum, args[0], args[cur_arg + 1 ]);
1844 err_code |= ERR_ALERT | ERR_FATAL;
1845 goto out;
1846 }
1847
1848 curproxy->listen->perm.ux.uid = user->pw_uid;
1849 cur_arg += 2;
1850 continue;
1851 }
1852
1853 if (!strcmp(args[cur_arg], "group")) {
1854 struct group *group;
1855
1856 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1857 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1858 file, linenum, args[0], args[cur_arg]);
1859 err_code |= ERR_ALERT | ERR_FATAL;
1860 goto out;
1861 }
1862 group = getgrnam(args[cur_arg + 1]);
1863 if (!group) {
1864 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1865 file, linenum, args[0], args[cur_arg + 1 ]);
1866 err_code |= ERR_ALERT | ERR_FATAL;
1867 goto out;
1868 }
1869
1870 curproxy->listen->perm.ux.gid = group->gr_gid;
1871 cur_arg += 2;
1872 continue;
1873 }
1874
Willy Tarreaub48f9582011-09-05 01:17:06 +02001875 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 +01001876 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001879 }
Willy Tarreau93893792009-07-23 13:19:11 +02001880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001881 }
1882 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1883 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1884 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1885 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001889 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001890 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001891
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 /* flush useless bits */
1893 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001896 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001898 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899
Willy Tarreau1c47f852006-07-09 08:22:27 +02001900 if (!*args[1]) {
1901 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1902 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001903 err_code |= ERR_ALERT | ERR_FATAL;
1904 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001905 }
1906
Willy Tarreaua534fea2008-08-03 12:19:50 +02001907 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001908 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001909 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001910 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001911 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1912
Willy Tarreau93893792009-07-23 13:19:11 +02001913 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1916 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1917 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1918 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1919 else {
1920 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_FATAL;
1922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 }
1924 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001925 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001926 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001927
1928 if (curproxy == &defproxy) {
1929 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001931 err_code |= ERR_ALERT | ERR_FATAL;
1932 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001933 }
1934
1935 if (!*args[1]) {
1936 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1937 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001938 err_code |= ERR_ALERT | ERR_FATAL;
1939 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001940 }
1941
1942 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001943 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001944
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001945 if (curproxy->uuid <= 0) {
1946 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001947 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001948 err_code |= ERR_ALERT | ERR_FATAL;
1949 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001950 }
1951
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001952 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1953 if (node) {
1954 struct proxy *target = container_of(node, struct proxy, conf.id);
1955 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1956 file, linenum, proxy_type_str(curproxy), curproxy->id,
1957 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1958 err_code |= ERR_ALERT | ERR_FATAL;
1959 goto out;
1960 }
1961 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001962 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001963 else if (!strcmp(args[0], "description")) {
1964 int i, len=0;
1965 char *d;
1966
Cyril Bonté99ed3272010-01-24 23:29:44 +01001967 if (curproxy == &defproxy) {
1968 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1969 file, linenum, args[0]);
1970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
1972 }
1973
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001974 if (!*args[1]) {
1975 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1976 file, linenum, args[0]);
1977 return -1;
1978 }
1979
1980 for(i=1; *args[i]; i++)
1981 len += strlen(args[i])+1;
1982
1983 d = (char *)calloc(1, len);
1984 curproxy->desc = d;
1985
1986 d += sprintf(d, "%s", args[1]);
1987 for(i=2; *args[i]; i++)
1988 d += sprintf(d, " %s", args[i]);
1989
1990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1992 curproxy->state = PR_STSTOPPED;
1993 }
1994 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1995 curproxy->state = PR_STNEW;
1996 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001997 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1998 int cur_arg = 1;
1999 unsigned int set = 0;
2000
2001 while (*args[cur_arg]) {
2002 int u;
2003 if (strcmp(args[cur_arg], "all") == 0) {
2004 set = 0;
2005 break;
2006 }
2007 else if (strcmp(args[cur_arg], "odd") == 0) {
2008 set |= 0x55555555;
2009 }
2010 else if (strcmp(args[cur_arg], "even") == 0) {
2011 set |= 0xAAAAAAAA;
2012 }
2013 else {
2014 u = str2uic(args[cur_arg]);
2015 if (u < 1 || u > 32) {
2016 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2017 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002020 }
2021 if (u > global.nbproc) {
2022 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2023 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002025 }
2026 set |= 1 << (u - 1);
2027 }
2028 cur_arg++;
2029 }
2030 curproxy->bind_proc = set;
2031 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002032 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002033 if (curproxy == &defproxy) {
2034 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002035 err_code |= ERR_ALERT | ERR_FATAL;
2036 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002037 }
2038
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002039 err = invalid_char(args[1]);
2040 if (err) {
2041 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2042 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002044 }
2045
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002046 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2047 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2048 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002051 }
2052 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2054 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002055
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002058
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 if (*(args[1]) == 0) {
2060 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2061 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002062 err_code |= ERR_ALERT | ERR_FATAL;
2063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002064 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002065
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002066 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002067 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002068 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002069 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002070 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 curproxy->cookie_name = strdup(args[1]);
2072 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002073
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 cur_arg = 2;
2075 while (*(args[cur_arg])) {
2076 if (!strcmp(args[cur_arg], "rewrite")) {
2077 curproxy->options |= PR_O_COOK_RW;
2078 }
2079 else if (!strcmp(args[cur_arg], "indirect")) {
2080 curproxy->options |= PR_O_COOK_IND;
2081 }
2082 else if (!strcmp(args[cur_arg], "insert")) {
2083 curproxy->options |= PR_O_COOK_INS;
2084 }
2085 else if (!strcmp(args[cur_arg], "nocache")) {
2086 curproxy->options |= PR_O_COOK_NOC;
2087 }
2088 else if (!strcmp(args[cur_arg], "postonly")) {
2089 curproxy->options |= PR_O_COOK_POST;
2090 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002091 else if (!strcmp(args[cur_arg], "preserve")) {
2092 curproxy->options2 |= PR_O2_COOK_PSV;
2093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 else if (!strcmp(args[cur_arg], "prefix")) {
2095 curproxy->options |= PR_O_COOK_PFX;
2096 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002097 else if (!strcmp(args[cur_arg], "domain")) {
2098 if (!*args[cur_arg + 1]) {
2099 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2100 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002101 err_code |= ERR_ALERT | ERR_FATAL;
2102 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002103 }
2104
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002105 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002106 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002107 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2108 " dots nor does not start with a dot."
2109 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002110 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002111 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002112 }
2113
2114 err = invalid_domainchar(args[cur_arg + 1]);
2115 if (err) {
2116 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2117 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002118 err_code |= ERR_ALERT | ERR_FATAL;
2119 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002120 }
2121
Willy Tarreau68a897b2009-12-03 23:28:34 +01002122 if (!curproxy->cookie_domain) {
2123 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2124 } else {
2125 /* one domain was already specified, add another one by
2126 * building the string which will be returned along with
2127 * the cookie.
2128 */
2129 char *new_ptr;
2130 int new_len = strlen(curproxy->cookie_domain) +
2131 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2132 new_ptr = malloc(new_len);
2133 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2134 free(curproxy->cookie_domain);
2135 curproxy->cookie_domain = new_ptr;
2136 }
Willy Tarreau31936852010-10-06 16:59:56 +02002137 cur_arg++;
2138 }
2139 else if (!strcmp(args[cur_arg], "maxidle")) {
2140 unsigned int maxidle;
2141 const char *res;
2142
2143 if (!*args[cur_arg + 1]) {
2144 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2145 file, linenum, args[cur_arg]);
2146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
2148 }
2149
2150 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2151 if (res) {
2152 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2153 file, linenum, *res, args[cur_arg]);
2154 err_code |= ERR_ALERT | ERR_FATAL;
2155 goto out;
2156 }
2157 curproxy->cookie_maxidle = maxidle;
2158 cur_arg++;
2159 }
2160 else if (!strcmp(args[cur_arg], "maxlife")) {
2161 unsigned int maxlife;
2162 const char *res;
2163
2164 if (!*args[cur_arg + 1]) {
2165 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2166 file, linenum, args[cur_arg]);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
2171 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2172 if (res) {
2173 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2174 file, linenum, *res, args[cur_arg]);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002179 cur_arg++;
2180 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002181 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002182 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 +02002183 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 }
2187 cur_arg++;
2188 }
2189 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2190 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2191 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002192 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 }
2194
2195 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2196 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2197 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002200
2201 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2202 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2203 file, linenum);
2204 err_code |= ERR_ALERT | ERR_FATAL;
2205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002207 else if (!strcmp(args[0], "persist")) { /* persist */
2208 if (*(args[1]) == 0) {
2209 Alert("parsing [%s:%d] : missing persist method.\n",
2210 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002211 err_code |= ERR_ALERT | ERR_FATAL;
2212 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002213 }
2214
2215 if (!strncmp(args[1], "rdp-cookie", 10)) {
2216 curproxy->options2 |= PR_O2_RDPC_PRST;
2217
Emeric Brunb982a3d2010-01-04 15:45:53 +01002218 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002219 const char *beg, *end;
2220
2221 beg = args[1] + 11;
2222 end = strchr(beg, ')');
2223
2224 if (!end || end == beg) {
2225 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2226 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002229 }
2230
2231 free(curproxy->rdp_cookie_name);
2232 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2233 curproxy->rdp_cookie_len = end-beg;
2234 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002235 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002236 free(curproxy->rdp_cookie_name);
2237 curproxy->rdp_cookie_name = strdup("msts");
2238 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2239 }
2240 else { /* syntax */
2241 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2242 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002245 }
2246 }
2247 else {
2248 Alert("parsing [%s:%d] : unknown persist method.\n",
2249 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002252 }
2253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002255 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002257 if (curproxy == &defproxy) {
2258 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
Willy Tarreau977b8e42006-12-29 14:19:17 +01002263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002265
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002267 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 }
2272 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002273 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 curproxy->appsession_name = strdup(args[1]);
2275 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2276 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002277 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2278 if (err) {
2279 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2280 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002283 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002284 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002285
Willy Tarreau51041c72007-09-09 21:56:53 +02002286 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2287 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002288 err_code |= ERR_ALERT | ERR_ABORT;
2289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002290 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002291
2292 cur_arg = 6;
2293 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002294 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2295 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002296 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002297 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002298 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002299 } else if (!strcmp(args[cur_arg], "prefix")) {
2300 curproxy->options2 |= PR_O2_AS_PFX;
2301 } else if (!strcmp(args[cur_arg], "mode")) {
2302 if (!*args[cur_arg + 1]) {
2303 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2304 file, linenum, args[0], args[cur_arg]);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308
2309 cur_arg++;
2310 if (!strcmp(args[cur_arg], "query-string")) {
2311 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2312 curproxy->options2 |= PR_O2_AS_M_QS;
2313 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2314 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2315 curproxy->options2 |= PR_O2_AS_M_PP;
2316 } else {
2317 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
2320 }
2321 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002322 cur_arg++;
2323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 } /* Url App Session */
2325 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002326 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002327 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002328
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002330 if (curproxy == &defproxy) {
2331 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2332 err_code |= ERR_ALERT | ERR_FATAL;
2333 goto out;
2334 }
2335
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 if (*(args[4]) == 0) {
2337 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2338 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002342 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 curproxy->capture_name = strdup(args[2]);
2344 curproxy->capture_namelen = strlen(curproxy->capture_name);
2345 curproxy->capture_len = atol(args[4]);
2346 if (curproxy->capture_len >= CAPTURE_LEN) {
2347 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2348 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 curproxy->capture_len = CAPTURE_LEN - 1;
2351 }
2352 curproxy->to_log |= LW_COOKIE;
2353 }
2354 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2355 struct cap_hdr *hdr;
2356
2357 if (curproxy == &defproxy) {
2358 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 +02002359 err_code |= ERR_ALERT | ERR_FATAL;
2360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362
2363 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2364 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2365 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
2369
2370 hdr = calloc(sizeof(struct cap_hdr), 1);
2371 hdr->next = curproxy->req_cap;
2372 hdr->name = strdup(args[3]);
2373 hdr->namelen = strlen(args[3]);
2374 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002375 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376 hdr->index = curproxy->nb_req_cap++;
2377 curproxy->req_cap = hdr;
2378 curproxy->to_log |= LW_REQHDR;
2379 }
2380 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2381 struct cap_hdr *hdr;
2382
2383 if (curproxy == &defproxy) {
2384 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 +02002385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
2388
2389 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2390 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2391 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394 }
2395 hdr = calloc(sizeof(struct cap_hdr), 1);
2396 hdr->next = curproxy->rsp_cap;
2397 hdr->name = strdup(args[3]);
2398 hdr->namelen = strlen(args[3]);
2399 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002400 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 hdr->index = curproxy->nb_rsp_cap++;
2402 curproxy->rsp_cap = hdr;
2403 curproxy->to_log |= LW_RSPHDR;
2404 }
2405 else {
2406 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2407 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }
2411 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002413 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002415
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 if (*(args[1]) == 0) {
2417 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2418 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422 curproxy->conn_retries = atol(args[1]);
2423 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002424 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002425 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002426
2427 if (curproxy == &defproxy) {
2428 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
2431 }
2432
Willy Tarreauff011f22011-01-06 17:51:27 +01002433 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 +01002434 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2435 file, linenum, args[0]);
2436 err_code |= ERR_WARN;
2437 }
2438
Willy Tarreauff011f22011-01-06 17:51:27 +01002439 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002440
Willy Tarreauff011f22011-01-06 17:51:27 +01002441 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002442 err_code |= ERR_ALERT | ERR_ABORT;
2443 goto out;
2444 }
2445
Willy Tarreauff011f22011-01-06 17:51:27 +01002446 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2447 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002448 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002449 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002450 if (curproxy == &defproxy) {
2451 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002454 }
2455
Willy Tarreauef6494c2010-01-28 17:12:36 +01002456 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002457 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002461 }
2462
Willy Tarreauef6494c2010-01-28 17:12:36 +01002463 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002464 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2465 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002468 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002469
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002470 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002471 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002472 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002473 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002474 struct redirect_rule *rule;
2475 int cur_arg;
2476 int type = REDIRECT_TYPE_NONE;
2477 int code = 302;
2478 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002479 char *cookie = NULL;
2480 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002481 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002482
Cyril Bonté99ed3272010-01-24 23:29:44 +01002483 if (curproxy == &defproxy) {
2484 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 goto out;
2487 }
2488
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002489 cur_arg = 1;
2490 while (*(args[cur_arg])) {
2491 if (!strcmp(args[cur_arg], "location")) {
2492 if (!*args[cur_arg + 1]) {
2493 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2494 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002497 }
2498
2499 type = REDIRECT_TYPE_LOCATION;
2500 cur_arg++;
2501 destination = args[cur_arg];
2502 }
2503 else if (!strcmp(args[cur_arg], "prefix")) {
2504 if (!*args[cur_arg + 1]) {
2505 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2506 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002509 }
2510
2511 type = REDIRECT_TYPE_PREFIX;
2512 cur_arg++;
2513 destination = args[cur_arg];
2514 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002515 else if (!strcmp(args[cur_arg], "set-cookie")) {
2516 if (!*args[cur_arg + 1]) {
2517 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2518 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002521 }
2522
2523 cur_arg++;
2524 cookie = args[cur_arg];
2525 cookie_set = 1;
2526 }
2527 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2528 if (!*args[cur_arg + 1]) {
2529 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2530 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002533 }
2534
2535 cur_arg++;
2536 cookie = args[cur_arg];
2537 cookie_set = 0;
2538 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002539 else if (!strcmp(args[cur_arg],"code")) {
2540 if (!*args[cur_arg + 1]) {
2541 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002545 }
2546 cur_arg++;
2547 code = atol(args[cur_arg]);
2548 if (code < 301 || code > 303) {
2549 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2550 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002553 }
2554 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002555 else if (!strcmp(args[cur_arg],"drop-query")) {
2556 flags |= REDIRECT_FLAG_DROP_QS;
2557 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002558 else if (!strcmp(args[cur_arg],"append-slash")) {
2559 flags |= REDIRECT_FLAG_APPEND_SLASH;
2560 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002561 else if (strcmp(args[cur_arg], "if") == 0 ||
2562 strcmp(args[cur_arg], "unless") == 0) {
2563 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2564 if (!cond) {
2565 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2566 file, linenum, args[0]);
2567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
2569 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002570 break;
2571 }
2572 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002573 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 +02002574 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002577 }
2578 cur_arg++;
2579 }
2580
2581 if (type == REDIRECT_TYPE_NONE) {
2582 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 }
2587
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002588 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2589 rule->cond = cond;
2590 rule->rdr_str = strdup(destination);
2591 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002592 if (cookie) {
2593 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002594 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002595 */
2596 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002597 if (cookie_set) {
2598 rule->cookie_str = malloc(rule->cookie_len + 10);
2599 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2600 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2601 rule->cookie_len += 9;
2602 } else {
2603 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002604 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002605 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2606 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002607 }
2608 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002609 rule->type = type;
2610 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002611 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002612 LIST_INIT(&rule->list);
2613 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002614 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2615 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002616 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002617 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002618 struct switching_rule *rule;
2619
Willy Tarreaub099aca2008-10-12 17:26:37 +02002620 if (curproxy == &defproxy) {
2621 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002624 }
2625
Willy Tarreau55ea7572007-06-17 19:56:27 +02002626 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002628
2629 if (*(args[1]) == 0) {
2630 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002633 }
2634
Willy Tarreauef6494c2010-01-28 17:12:36 +01002635 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002636 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2637 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002640 }
2641
Willy Tarreauef6494c2010-01-28 17:12:36 +01002642 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002643 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002644 file, linenum);
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 Tarreauf1e98b82010-01-28 17:59:39 +01002649 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002650
Willy Tarreau55ea7572007-06-17 19:56:27 +02002651 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2652 rule->cond = cond;
2653 rule->be.name = strdup(args[1]);
2654 LIST_INIT(&rule->list);
2655 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2656 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002657 else if ((!strcmp(args[0], "force-persist")) ||
2658 (!strcmp(args[0], "ignore-persist"))) {
2659 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002660
2661 if (curproxy == &defproxy) {
2662 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2663 err_code |= ERR_ALERT | ERR_FATAL;
2664 goto out;
2665 }
2666
2667 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2668 err_code |= ERR_WARN;
2669
Willy Tarreauef6494c2010-01-28 17:12:36 +01002670 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002671 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2672 file, linenum, args[0]);
2673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676
Willy Tarreauef6494c2010-01-28 17:12:36 +01002677 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002678 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2679 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
2682 }
2683
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002684 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002685
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002686 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002687 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002688 if (!strcmp(args[0], "force-persist")) {
2689 rule->type = PERSIST_TYPE_FORCE;
2690 } else {
2691 rule->type = PERSIST_TYPE_IGNORE;
2692 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002693 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002694 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002695 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002696 else if (!strcmp(args[0], "stick-table")) {
2697 int myidx = 1;
2698
Emeric Brun32da3c42010-09-23 18:39:19 +02002699 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002700 curproxy->table.type = (unsigned int)-1;
2701 while (*args[myidx]) {
2702 const char *err;
2703
2704 if (strcmp(args[myidx], "size") == 0) {
2705 myidx++;
2706 if (!*(args[myidx])) {
2707 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2708 file, linenum, args[myidx-1]);
2709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
2711 }
2712 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2713 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2714 file, linenum, *err, args[myidx-1]);
2715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
2717 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002718 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002719 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002720 else if (strcmp(args[myidx], "peers") == 0) {
2721 myidx++;
2722 if (!*(args[myidx])) {
2723 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2724 file, linenum, args[myidx-1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728 curproxy->table.peers.name = strdup(args[myidx++]);
2729 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002730 else if (strcmp(args[myidx], "expire") == 0) {
2731 myidx++;
2732 if (!*(args[myidx])) {
2733 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2734 file, linenum, args[myidx-1]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2739 if (err) {
2740 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2741 file, linenum, *err, args[myidx-1]);
2742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
2744 }
2745 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002746 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002747 }
2748 else if (strcmp(args[myidx], "nopurge") == 0) {
2749 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002750 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002751 }
2752 else if (strcmp(args[myidx], "type") == 0) {
2753 myidx++;
2754 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2755 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2756 file, linenum, args[myidx]);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002760 /* myidx already points to next arg */
2761 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002762 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002763 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002764 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002765
2766 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002767 nw = args[myidx];
2768 while (*nw) {
2769 /* the "store" keyword supports a comma-separated list */
2770 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002771 sa = NULL; /* store arg */
2772 while (*nw && *nw != ',') {
2773 if (*nw == '(') {
2774 *nw = 0;
2775 sa = ++nw;
2776 while (*nw != ')') {
2777 if (!*nw) {
2778 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2779 file, linenum, args[0], cw);
2780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
2783 nw++;
2784 }
2785 *nw = '\0';
2786 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002787 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002788 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002789 if (*nw)
2790 *nw++ = '\0';
2791 type = stktable_get_data_type(cw);
2792 if (type < 0) {
2793 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2794 file, linenum, args[0], cw);
2795 err_code |= ERR_ALERT | ERR_FATAL;
2796 goto out;
2797 }
Willy Tarreauac782882010-06-20 10:41:54 +02002798
2799 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2800 switch (err) {
2801 case PE_NONE: break;
2802 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002803 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2804 file, linenum, args[0], cw);
2805 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002806 break;
2807
2808 case PE_ARG_MISSING:
2809 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2810 file, linenum, args[0], cw);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
2813
2814 case PE_ARG_NOT_USED:
2815 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2816 file, linenum, args[0], cw);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819
2820 default:
2821 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2822 file, linenum, args[0], cw);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002825 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002826 }
2827 myidx++;
2828 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002829 else {
2830 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2831 file, linenum, args[myidx]);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002834 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002835 }
2836
2837 if (!curproxy->table.size) {
2838 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2839 file, linenum);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843
2844 if (curproxy->table.type == (unsigned int)-1) {
2845 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2846 file, linenum);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
2850 }
2851 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002852 struct sticking_rule *rule;
2853 struct pattern_expr *expr;
2854 int myidx = 0;
2855 const char *name = NULL;
2856 int flags;
2857
2858 if (curproxy == &defproxy) {
2859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2860 err_code |= ERR_ALERT | ERR_FATAL;
2861 goto out;
2862 }
2863
2864 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2865 err_code |= ERR_WARN;
2866 goto out;
2867 }
2868
2869 myidx++;
2870 if ((strcmp(args[myidx], "store") == 0) ||
2871 (strcmp(args[myidx], "store-request") == 0)) {
2872 myidx++;
2873 flags = STK_IS_STORE;
2874 }
2875 else if (strcmp(args[myidx], "store-response") == 0) {
2876 myidx++;
2877 flags = STK_IS_STORE | STK_ON_RSP;
2878 }
2879 else if (strcmp(args[myidx], "match") == 0) {
2880 myidx++;
2881 flags = STK_IS_MATCH;
2882 }
2883 else if (strcmp(args[myidx], "on") == 0) {
2884 myidx++;
2885 flags = STK_IS_MATCH | STK_IS_STORE;
2886 }
2887 else {
2888 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
2891 }
2892
2893 if (*(args[myidx]) == 0) {
2894 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
2897 }
2898
Emeric Brun485479d2010-09-23 18:02:19 +02002899 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002900 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002901 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905
2906 if (flags & STK_ON_RSP) {
2907 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2908 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2909 file, linenum, args[0], expr->fetch->kw);
2910 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002911 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002912 goto out;
2913 }
2914 } else {
2915 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2916 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2917 file, linenum, args[0], expr->fetch->kw);
2918 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002919 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002920 goto out;
2921 }
2922 }
2923
2924 if (strcmp(args[myidx], "table") == 0) {
2925 myidx++;
2926 name = args[myidx++];
2927 }
2928
Willy Tarreauef6494c2010-01-28 17:12:36 +01002929 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2930 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002931 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2932 file, linenum, args[0]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002934 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 goto out;
2936 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002937 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002938 else if (*(args[myidx])) {
2939 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2940 file, linenum, args[0], args[myidx]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002942 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002943 goto out;
2944 }
Emeric Brun97679e72010-09-23 17:56:44 +02002945 if (flags & STK_ON_RSP)
2946 err_code |= warnif_cond_requires_req(cond, file, linenum);
2947 else
2948 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002949
Emeric Brunb982a3d2010-01-04 15:45:53 +01002950 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2951 rule->cond = cond;
2952 rule->expr = expr;
2953 rule->flags = flags;
2954 rule->table.name = name ? strdup(name) : NULL;
2955 LIST_INIT(&rule->list);
2956 if (flags & STK_ON_RSP)
2957 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2958 else
2959 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002962 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002964
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2966 curproxy->uri_auth = NULL; /* we must detach from the default config */
2967
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002968 if (!*args[1]) {
2969 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002970 } else if (!strcmp(args[1], "admin")) {
2971 struct stats_admin_rule *rule;
2972
2973 if (curproxy == &defproxy) {
2974 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
2977 }
2978
2979 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2980 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2981 err_code |= ERR_ALERT | ERR_ABORT;
2982 goto out;
2983 }
2984
2985 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2986 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2987 file, linenum, args[0], args[1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2992 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2993 file, linenum, args[0], args[1]);
2994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
2996 }
2997
2998 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2999
3000 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3001 rule->cond = cond;
3002 LIST_INIT(&rule->list);
3003 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 } else if (!strcmp(args[1], "uri")) {
3005 if (*(args[2]) == 0) {
3006 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003007 err_code |= ERR_ALERT | ERR_FATAL;
3008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3010 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_ABORT;
3012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 }
3014 } else if (!strcmp(args[1], "realm")) {
3015 if (*(args[2]) == 0) {
3016 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3020 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003021 err_code |= ERR_ALERT | ERR_ABORT;
3022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003024 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003025 unsigned interval;
3026
3027 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3028 if (err) {
3029 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3030 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003033 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
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 Tarreaubbd42122007-07-25 07:26:38 +02003037 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003038 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003039 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003040
3041 if (curproxy == &defproxy) {
3042 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046
3047 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3048 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3049 err_code |= ERR_ALERT | ERR_ABORT;
3050 goto out;
3051 }
3052
Willy Tarreauff011f22011-01-06 17:51:27 +01003053 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3054 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003055 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3056 file, linenum, args[0]);
3057 err_code |= ERR_WARN;
3058 }
3059
Willy Tarreauff011f22011-01-06 17:51:27 +01003060 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003061
Willy Tarreauff011f22011-01-06 17:51:27 +01003062 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003063 err_code |= ERR_ALERT | ERR_ABORT;
3064 goto out;
3065 }
3066
Willy Tarreauff011f22011-01-06 17:51:27 +01003067 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3068 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003069
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 } else if (!strcmp(args[1], "auth")) {
3071 if (*(args[2]) == 0) {
3072 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3076 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_ALERT | ERR_ABORT;
3078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
3080 } else if (!strcmp(args[1], "scope")) {
3081 if (*(args[2]) == 0) {
3082 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3086 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003087 err_code |= ERR_ALERT | ERR_ABORT;
3088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 }
3090 } else if (!strcmp(args[1], "enable")) {
3091 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3092 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003093 err_code |= ERR_ALERT | ERR_ABORT;
3094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003095 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003096 } else if (!strcmp(args[1], "hide-version")) {
3097 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3098 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003099 err_code |= ERR_ALERT | ERR_ABORT;
3100 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003101 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003102 } else if (!strcmp(args[1], "show-legends")) {
3103 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3104 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3105 err_code |= ERR_ALERT | ERR_ABORT;
3106 goto out;
3107 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003108 } else if (!strcmp(args[1], "show-node")) {
3109
3110 if (*args[2]) {
3111 int i;
3112 char c;
3113
3114 for (i=0; args[2][i]; i++) {
3115 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003116 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3117 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003118 break;
3119 }
3120
3121 if (!i || args[2][i]) {
3122 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3123 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3124 file, linenum, args[0], args[1]);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127 }
3128 }
3129
3130 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3131 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3132 err_code |= ERR_ALERT | ERR_ABORT;
3133 goto out;
3134 }
3135 } else if (!strcmp(args[1], "show-desc")) {
3136 char *desc = NULL;
3137
3138 if (*args[2]) {
3139 int i, len=0;
3140 char *d;
3141
3142 for(i=2; *args[i]; i++)
3143 len += strlen(args[i])+1;
3144
3145 desc = d = (char *)calloc(1, len);
3146
3147 d += sprintf(d, "%s", args[2]);
3148 for(i=3; *args[i]; i++)
3149 d += sprintf(d, " %s", args[i]);
3150 }
3151
3152 if (!*args[2] && !global.desc)
3153 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3154 file, linenum, args[1]);
3155 else {
3156 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3157 free(desc);
3158 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3159 err_code |= ERR_ALERT | ERR_ABORT;
3160 goto out;
3161 }
3162 free(desc);
3163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003165stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003166 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 +01003167 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 }
3171 }
3172 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003173 int optnum;
3174
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003175 if (*(args[1]) == '\0') {
3176 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3177 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003181
3182 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3183 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003184 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3185 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3186 file, linenum, cfg_opts[optnum].name);
3187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
3189 }
Willy Tarreau93893792009-07-23 13:19:11 +02003190 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3191 err_code |= ERR_WARN;
3192 goto out;
3193 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003194
Willy Tarreau3842f002009-06-14 11:39:52 +02003195 curproxy->no_options &= ~cfg_opts[optnum].val;
3196 curproxy->options &= ~cfg_opts[optnum].val;
3197
3198 switch (kwm) {
3199 case KWM_STD:
3200 curproxy->options |= cfg_opts[optnum].val;
3201 break;
3202 case KWM_NO:
3203 curproxy->no_options |= cfg_opts[optnum].val;
3204 break;
3205 case KWM_DEF: /* already cleared */
3206 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003207 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003208
Willy Tarreau93893792009-07-23 13:19:11 +02003209 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003210 }
3211 }
3212
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003213 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3214 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003215 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3216 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3217 file, linenum, cfg_opts2[optnum].name);
3218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
Willy Tarreau93893792009-07-23 13:19:11 +02003221 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3222 err_code |= ERR_WARN;
3223 goto out;
3224 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003225
Willy Tarreau3842f002009-06-14 11:39:52 +02003226 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3227 curproxy->options2 &= ~cfg_opts2[optnum].val;
3228
3229 switch (kwm) {
3230 case KWM_STD:
3231 curproxy->options2 |= cfg_opts2[optnum].val;
3232 break;
3233 case KWM_NO:
3234 curproxy->no_options2 |= cfg_opts2[optnum].val;
3235 break;
3236 case KWM_DEF: /* already cleared */
3237 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003238 }
Willy Tarreau93893792009-07-23 13:19:11 +02003239 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003240 }
3241 }
3242
Willy Tarreau3842f002009-06-14 11:39:52 +02003243 if (kwm != KWM_STD) {
3244 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003245 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003248 }
3249
Emeric Brun3a058f32009-06-30 18:26:00 +02003250 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003252 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003254 if (*(args[2]) != '\0') {
3255 if (!strcmp(args[2], "clf")) {
3256 curproxy->options2 |= PR_O2_CLFLOG;
3257 } else {
3258 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003259 err_code |= ERR_ALERT | ERR_FATAL;
3260 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003261 }
3262 }
3263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 else if (!strcmp(args[1], "tcplog"))
3265 /* generate a detailed TCP log */
3266 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 else if (!strcmp(args[1], "tcpka")) {
3268 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003269 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003271
3272 if (curproxy->cap & PR_CAP_FE)
3273 curproxy->options |= PR_O_TCP_CLI_KA;
3274 if (curproxy->cap & PR_CAP_BE)
3275 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003278 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_WARN;
3280
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003282 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003283 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003284 curproxy->options2 &= ~PR_O2_CHK_ANY;
3285 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 if (!*args[2]) { /* no argument */
3287 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3288 curproxy->check_len = strlen(DEF_CHECK_REQ);
3289 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003290 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 curproxy->check_req = (char *)malloc(reqlen);
3292 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003293 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003295 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 if (*args[4])
3297 reqlen += strlen(args[4]);
3298 else
3299 reqlen += strlen("HTTP/1.0");
3300
3301 curproxy->check_req = (char *)malloc(reqlen);
3302 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003303 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003305 }
3306 else if (!strcmp(args[1], "ssl-hello-chk")) {
3307 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003308 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003310
Willy Tarreaua534fea2008-08-03 12:19:50 +02003311 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003312 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003313 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003314 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 }
Willy Tarreau23677902007-05-08 23:50:35 +02003316 else if (!strcmp(args[1], "smtpchk")) {
3317 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003318 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003319 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003320 curproxy->options2 &= ~PR_O2_CHK_ANY;
3321 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003322
3323 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3324 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3325 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3326 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3327 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3328 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3329 curproxy->check_req = (char *)malloc(reqlen);
3330 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3331 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3332 } else {
3333 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3334 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3335 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3336 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3337 }
3338 }
3339 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003340 else if (!strcmp(args[1], "pgsql-check")) {
3341 /* use PostgreSQL request to check servers' health */
3342 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3343 err_code |= ERR_WARN;
3344
3345 free(curproxy->check_req);
3346 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003347 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003348 curproxy->options2 |= PR_O2_PGSQL_CHK;
3349
3350 if (*(args[2])) {
3351 int cur_arg = 2;
3352
3353 while (*(args[cur_arg])) {
3354 if (strcmp(args[cur_arg], "user") == 0) {
3355 char * packet;
3356 uint32_t packet_len;
3357 uint32_t pv;
3358
3359 /* suboption header - needs additional argument for it */
3360 if (*(args[cur_arg+1]) == 0) {
3361 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3362 file, linenum, args[0], args[1], args[cur_arg]);
3363 err_code |= ERR_ALERT | ERR_FATAL;
3364 goto out;
3365 }
3366
3367 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3368 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3369 pv = htonl(0x30000); /* protocol version 3.0 */
3370
3371 packet = (char*) calloc(1, packet_len);
3372
3373 memcpy(packet + 4, &pv, 4);
3374
3375 /* copy "user" */
3376 memcpy(packet + 8, "user", 4);
3377
3378 /* copy username */
3379 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3380
3381 free(curproxy->check_req);
3382 curproxy->check_req = packet;
3383 curproxy->check_len = packet_len;
3384
3385 packet_len = htonl(packet_len);
3386 memcpy(packet, &packet_len, 4);
3387 cur_arg += 2;
3388 } else {
3389 /* unknown suboption - catchall */
3390 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3391 file, linenum, args[0], args[1]);
3392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
3394 }
3395 } /* end while loop */
3396 }
3397 }
3398
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003399 else if (!strcmp(args[1], "redis-check")) {
3400 /* use REDIS PING request to check servers' health */
3401 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3402 err_code |= ERR_WARN;
3403
3404 free(curproxy->check_req);
3405 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003406 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003407 curproxy->options2 |= PR_O2_REDIS_CHK;
3408
3409 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3410 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3411 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3412 }
3413
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003414 else if (!strcmp(args[1], "mysql-check")) {
3415 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003416 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3417 err_code |= ERR_WARN;
3418
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003419 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003420 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003421 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003422 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003423
3424 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3425 * const char mysql40_client_auth_pkt[] = {
3426 * "\x0e\x00\x00" // packet length
3427 * "\x01" // packet number
3428 * "\x00\x00" // client capabilities
3429 * "\x00\x00\x01" // max packet
3430 * "haproxy\x00" // username (null terminated string)
3431 * "\x00" // filler (always 0x00)
3432 * "\x01\x00\x00" // packet length
3433 * "\x00" // packet number
3434 * "\x01" // COM_QUIT command
3435 * };
3436 */
3437
3438 if (*(args[2])) {
3439 int cur_arg = 2;
3440
3441 while (*(args[cur_arg])) {
3442 if (strcmp(args[cur_arg], "user") == 0) {
3443 char *mysqluser;
3444 int packetlen, reqlen, userlen;
3445
3446 /* suboption header - needs additional argument for it */
3447 if (*(args[cur_arg+1]) == 0) {
3448 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3449 file, linenum, args[0], args[1], args[cur_arg]);
3450 err_code |= ERR_ALERT | ERR_FATAL;
3451 goto out;
3452 }
3453 mysqluser = args[cur_arg + 1];
3454 userlen = strlen(mysqluser);
3455 packetlen = userlen + 7;
3456 reqlen = packetlen + 9;
3457
3458 free(curproxy->check_req);
3459 curproxy->check_req = (char *)calloc(1, reqlen);
3460 curproxy->check_len = reqlen;
3461
3462 snprintf(curproxy->check_req, 4, "%c%c%c",
3463 ((unsigned char) packetlen & 0xff),
3464 ((unsigned char) (packetlen >> 8) & 0xff),
3465 ((unsigned char) (packetlen >> 16) & 0xff));
3466
3467 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003468 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003469 curproxy->check_req[8] = 1;
3470 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3471 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3472 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3473 cur_arg += 2;
3474 } else {
3475 /* unknown suboption - catchall */
3476 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3477 file, linenum, args[0], args[1]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
3480 }
3481 } /* end while loop */
3482 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003483 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003484 else if (!strcmp(args[1], "ldap-check")) {
3485 /* use LDAP request to check servers' health */
3486 free(curproxy->check_req);
3487 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003488 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003489 curproxy->options2 |= PR_O2_LDAP_CHK;
3490
3491 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3492 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3493 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3494 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003495 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003496 int cur_arg;
3497
3498 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3499 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003500 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003501
Willy Tarreau87cf5142011-08-19 22:57:24 +02003502 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003503
3504 free(curproxy->fwdfor_hdr_name);
3505 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3506 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3507
3508 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3509 cur_arg = 2;
3510 while (*(args[cur_arg])) {
3511 if (!strcmp(args[cur_arg], "except")) {
3512 /* suboption except - needs additional argument for it */
3513 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3514 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3515 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003518 }
3519 /* flush useless bits */
3520 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003521 cur_arg += 2;
3522 } else if (!strcmp(args[cur_arg], "header")) {
3523 /* suboption header - needs additional argument for it */
3524 if (*(args[cur_arg+1]) == 0) {
3525 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3526 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_FATAL;
3528 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003529 }
3530 free(curproxy->fwdfor_hdr_name);
3531 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3532 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3533 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003534 } else if (!strcmp(args[cur_arg], "if-none")) {
3535 curproxy->options &= ~PR_O_FF_ALWAYS;
3536 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003537 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003538 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003539 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003540 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003543 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003544 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003545 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003546 else if (!strcmp(args[1], "originalto")) {
3547 int cur_arg;
3548
3549 /* insert x-original-to field, but not for the IP address listed as an except.
3550 * set default options (ie: bitfield, header name, etc)
3551 */
3552
3553 curproxy->options |= PR_O_ORGTO;
3554
3555 free(curproxy->orgto_hdr_name);
3556 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3557 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3558
Willy Tarreau87cf5142011-08-19 22:57:24 +02003559 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003560 cur_arg = 2;
3561 while (*(args[cur_arg])) {
3562 if (!strcmp(args[cur_arg], "except")) {
3563 /* suboption except - needs additional argument for it */
3564 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3565 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3566 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003569 }
3570 /* flush useless bits */
3571 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3572 cur_arg += 2;
3573 } else if (!strcmp(args[cur_arg], "header")) {
3574 /* suboption header - needs additional argument for it */
3575 if (*(args[cur_arg+1]) == 0) {
3576 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3577 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_FATAL;
3579 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003580 }
3581 free(curproxy->orgto_hdr_name);
3582 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3583 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3584 cur_arg += 2;
3585 } else {
3586 /* unknown suboption - catchall */
3587 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3588 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003591 }
3592 } /* end while loop */
3593 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003594 else {
3595 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003598 }
Willy Tarreau93893792009-07-23 13:19:11 +02003599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003601 else if (!strcmp(args[0], "default_backend")) {
3602 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003604
3605 if (*(args[1]) == 0) {
3606 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003607 err_code |= ERR_ALERT | ERR_FATAL;
3608 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003609 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003610 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003611 curproxy->defbe.name = strdup(args[1]);
3612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003614 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003616
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003617 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3618 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003619 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003620 /* enable reconnections to dispatch */
3621 curproxy->options |= PR_O_REDISP;
3622 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003623 else if (!strcmp(args[0], "http-check")) {
3624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003626
3627 if (strcmp(args[1], "disable-on-404") == 0) {
3628 /* enable a graceful server shutdown on an HTTP 404 response */
3629 curproxy->options |= PR_O_DISABLE404;
3630 }
Willy Tarreauef781042010-01-27 11:53:01 +01003631 else if (strcmp(args[1], "send-state") == 0) {
3632 /* enable emission of the apparent state of a server in HTTP checks */
3633 curproxy->options2 |= PR_O2_CHK_SNDST;
3634 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003635 else if (strcmp(args[1], "expect") == 0) {
3636 const char *ptr_arg;
3637 int cur_arg;
3638
3639 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3640 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
3643 }
3644
3645 cur_arg = 2;
3646 /* consider exclamation marks, sole or at the beginning of a word */
3647 while (*(ptr_arg = args[cur_arg])) {
3648 while (*ptr_arg == '!') {
3649 curproxy->options2 ^= PR_O2_EXP_INV;
3650 ptr_arg++;
3651 }
3652 if (*ptr_arg)
3653 break;
3654 cur_arg++;
3655 }
3656 /* now ptr_arg points to the beginning of a word past any possible
3657 * exclamation mark, and cur_arg is the argument which holds this word.
3658 */
3659 if (strcmp(ptr_arg, "status") == 0) {
3660 if (!*(args[cur_arg + 1])) {
3661 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3662 file, linenum, args[0], args[1], ptr_arg);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003667 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003668 curproxy->expect_str = strdup(args[cur_arg + 1]);
3669 }
3670 else if (strcmp(ptr_arg, "string") == 0) {
3671 if (!*(args[cur_arg + 1])) {
3672 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3673 file, linenum, args[0], args[1], ptr_arg);
3674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
3676 }
3677 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003678 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003679 curproxy->expect_str = strdup(args[cur_arg + 1]);
3680 }
3681 else if (strcmp(ptr_arg, "rstatus") == 0) {
3682 if (!*(args[cur_arg + 1])) {
3683 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3684 file, linenum, args[0], args[1], ptr_arg);
3685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
3687 }
3688 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003689 free(curproxy->expect_str);
3690 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3691 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003692 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3693 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3694 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3695 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
3698 }
3699 }
3700 else if (strcmp(ptr_arg, "rstring") == 0) {
3701 if (!*(args[cur_arg + 1])) {
3702 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3703 file, linenum, args[0], args[1], ptr_arg);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003708 free(curproxy->expect_str);
3709 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3710 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003711 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3712 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3713 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3714 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3715 err_code |= ERR_ALERT | ERR_FATAL;
3716 goto out;
3717 }
3718 }
3719 else {
3720 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3721 file, linenum, args[0], args[1], ptr_arg);
3722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
3724 }
3725 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003726 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003727 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 +02003728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003730 }
3731 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003732 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003733 if (curproxy == &defproxy) {
3734 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003737 }
3738
Willy Tarreaub80c2302007-11-30 20:51:32 +01003739 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003741
3742 if (strcmp(args[1], "fail") == 0) {
3743 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003744 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003745 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3746 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003749 }
3750
Willy Tarreauef6494c2010-01-28 17:12:36 +01003751 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003752 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3753 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003756 }
3757 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3758 }
3759 else {
3760 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
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 Tarreaubaaee002006-06-26 02:48:02 +02003765#ifdef TPROXY
3766 else if (!strcmp(args[0], "transparent")) {
3767 /* enable transparent proxy connections */
3768 curproxy->options |= PR_O_TRANSP;
3769 }
3770#endif
3771 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003772 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774
Willy Tarreaubaaee002006-06-26 02:48:02 +02003775 if (*(args[1]) == 0) {
3776 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 }
3780 curproxy->maxconn = atol(args[1]);
3781 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003782 else if (!strcmp(args[0], "backlog")) { /* backlog */
3783 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003785
3786 if (*(args[1]) == 0) {
3787 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_FATAL;
3789 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003790 }
3791 curproxy->backlog = atol(args[1]);
3792 }
Willy Tarreau86034312006-12-29 00:10:33 +01003793 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003794 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003796
Willy Tarreau86034312006-12-29 00:10:33 +01003797 if (*(args[1]) == 0) {
3798 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003801 }
3802 curproxy->fullconn = atol(args[1]);
3803 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3805 if (*(args[1]) == 0) {
3806 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003810 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3811 if (err) {
3812 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3813 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003816 }
3817 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 }
3819 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003820 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 if (curproxy == &defproxy) {
3822 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003823 err_code |= ERR_ALERT | ERR_FATAL;
3824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003826 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003828
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 if (strchr(args[1], ':') == NULL) {
3830 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003834 sk = str2sa(args[1]);
3835 if (!sk) {
3836 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
3839 }
3840 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003841 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 }
3843 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003844 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003845 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003846
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003847 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003848 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3849 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003854 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3855 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3856 err_code |= ERR_WARN;
3857
3858 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3859 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3860 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3861 }
3862 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3863 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3864 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3865 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003866 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3867 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3868 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3869 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003870 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003871 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
3874 }
3875 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003876 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003878 char *rport, *raddr;
3879 short realport = 0;
3880 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003882 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_ALERT | ERR_FATAL;
3885 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003887 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889
3890 if (!*args[2]) {
3891 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3892 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003895 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003896
3897 err = invalid_char(args[1]);
3898 if (err) {
3899 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3900 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003903 }
3904
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003905 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003906 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003907
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003908 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3909 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3910 err_code |= ERR_ALERT | ERR_ABORT;
3911 goto out;
3912 }
3913
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003914 /* the servers are linked backwards first */
3915 newsrv->next = curproxy->srv;
3916 curproxy->srv = newsrv;
3917 newsrv->proxy = curproxy;
3918 newsrv->conf.file = file;
3919 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003920
Simon Hormanaf514952011-06-21 14:34:57 +09003921 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003922 LIST_INIT(&newsrv->pendconns);
3923 do_check = 0;
3924 newsrv->state = SRV_RUNNING; /* early server setup */
3925 newsrv->last_change = now.tv_sec;
3926 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003928 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003929 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003930 * - IP: => port=+0, relative
3931 * - IP:N => port=N, absolute
3932 * - IP:+N => port=+N, relative
3933 * - IP:-N => port=-N, relative
3934 */
3935 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003936 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003937 if (rport) {
3938 *rport++ = 0;
3939 realport = atol(rport);
3940 if (!isdigit((unsigned char)*rport))
3941 newsrv->state |= SRV_MAPPORTS;
3942 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003943 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003944
Willy Tarreaufab5a432011-03-04 15:31:53 +01003945 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003946 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003947 if (!sk) {
3948 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
3951 }
3952 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003953 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003954
3955 newsrv->check_port = curproxy->defsrv.check_port;
3956 newsrv->inter = curproxy->defsrv.inter;
3957 newsrv->fastinter = curproxy->defsrv.fastinter;
3958 newsrv->downinter = curproxy->defsrv.downinter;
3959 newsrv->rise = curproxy->defsrv.rise;
3960 newsrv->fall = curproxy->defsrv.fall;
3961 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3962 newsrv->minconn = curproxy->defsrv.minconn;
3963 newsrv->maxconn = curproxy->defsrv.maxconn;
3964 newsrv->slowstart = curproxy->defsrv.slowstart;
3965 newsrv->onerror = curproxy->defsrv.onerror;
3966 newsrv->consecutive_errors_limit
3967 = curproxy->defsrv.consecutive_errors_limit;
3968 newsrv->uweight = newsrv->iweight
3969 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003970
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003971 newsrv->curfd = -1; /* no health-check in progress */
3972 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003974 cur_arg = 3;
3975 } else {
3976 newsrv = &curproxy->defsrv;
3977 cur_arg = 1;
3978 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003979
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003981 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003982 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003983
3984 if (!*args[cur_arg + 1]) {
3985 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3986 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003989 }
3990
3991 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003992 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003993
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003994 if (newsrv->puid <= 0) {
3995 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003996 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003999 }
4000
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004001 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4002 if (node) {
4003 struct server *target = container_of(node, struct server, conf.id);
4004 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4005 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
4008 }
4009 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004010 cur_arg += 2;
4011 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004012 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 newsrv->cookie = strdup(args[cur_arg + 1]);
4014 newsrv->cklen = strlen(args[cur_arg + 1]);
4015 cur_arg += 2;
4016 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004017 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004018 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4019 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4020 cur_arg += 2;
4021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004023 if (!*args[cur_arg + 1]) {
4024 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4025 file, linenum, args[cur_arg]);
4026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
4028 }
4029
Willy Tarreaubaaee002006-06-26 02:48:02 +02004030 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004031 if (newsrv->rise <= 0) {
4032 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4033 file, linenum, args[cur_arg]);
4034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
4036 }
4037
Willy Tarreau96839092010-03-29 10:02:24 +02004038 if (newsrv->health)
4039 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 cur_arg += 2;
4041 }
4042 else if (!strcmp(args[cur_arg], "fall")) {
4043 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004044
4045 if (!*args[cur_arg + 1]) {
4046 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4047 file, linenum, args[cur_arg]);
4048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
4050 }
4051
4052 if (newsrv->fall <= 0) {
4053 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4054 file, linenum, args[cur_arg]);
4055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
4057 }
4058
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 cur_arg += 2;
4060 }
4061 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004062 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4063 if (err) {
4064 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4065 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004068 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004069 if (val <= 0) {
4070 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4071 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004074 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004075 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076 cur_arg += 2;
4077 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004078 else if (!strcmp(args[cur_arg], "fastinter")) {
4079 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4080 if (err) {
4081 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4082 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004085 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004086 if (val <= 0) {
4087 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4088 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004091 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004092 newsrv->fastinter = val;
4093 cur_arg += 2;
4094 }
4095 else if (!strcmp(args[cur_arg], "downinter")) {
4096 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4097 if (err) {
4098 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4099 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004102 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004103 if (val <= 0) {
4104 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4105 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004108 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004109 newsrv->downinter = val;
4110 cur_arg += 2;
4111 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004112 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004113 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004114 if (!sk) {
4115 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004120 cur_arg += 2;
4121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 else if (!strcmp(args[cur_arg], "port")) {
4123 newsrv->check_port = atol(args[cur_arg + 1]);
4124 cur_arg += 2;
4125 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004126 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 newsrv->state |= SRV_BACKUP;
4128 cur_arg ++;
4129 }
Simon Hormanfa461682011-06-25 09:39:49 +09004130 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4131 newsrv->state |= SRV_NON_STICK;
4132 cur_arg ++;
4133 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004134 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4135 newsrv->state |= SRV_SEND_PROXY;
4136 cur_arg ++;
4137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 else if (!strcmp(args[cur_arg], "weight")) {
4139 int w;
4140 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004141 if (w < 0 || w > 256) {
4142 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004147 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 cur_arg += 2;
4149 }
4150 else if (!strcmp(args[cur_arg], "minconn")) {
4151 newsrv->minconn = atol(args[cur_arg + 1]);
4152 cur_arg += 2;
4153 }
4154 else if (!strcmp(args[cur_arg], "maxconn")) {
4155 newsrv->maxconn = atol(args[cur_arg + 1]);
4156 cur_arg += 2;
4157 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004158 else if (!strcmp(args[cur_arg], "maxqueue")) {
4159 newsrv->maxqueue = atol(args[cur_arg + 1]);
4160 cur_arg += 2;
4161 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004162 else if (!strcmp(args[cur_arg], "slowstart")) {
4163 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004164 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004165 if (err) {
4166 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4167 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004170 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004171 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004172 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4173 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004176 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004177 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004178 cur_arg += 2;
4179 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004180 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004181
4182 if (!*args[cur_arg + 1]) {
4183 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4184 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004187 }
4188
4189 newsrv->trackit = strdup(args[cur_arg + 1]);
4190
4191 cur_arg += 2;
4192 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004193 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 global.maxsock++;
4195 do_check = 1;
4196 cur_arg += 1;
4197 }
Willy Tarreau96839092010-03-29 10:02:24 +02004198 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4199 newsrv->state |= SRV_MAINTAIN;
4200 newsrv->state &= ~SRV_RUNNING;
4201 newsrv->health = 0;
4202 cur_arg += 1;
4203 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004204 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004205 if (!strcmp(args[cur_arg + 1], "none"))
4206 newsrv->observe = HANA_OBS_NONE;
4207 else if (!strcmp(args[cur_arg + 1], "layer4"))
4208 newsrv->observe = HANA_OBS_LAYER4;
4209 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4210 if (curproxy->mode != PR_MODE_HTTP) {
4211 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4212 file, linenum, args[cur_arg + 1]);
4213 err_code |= ERR_ALERT;
4214 }
4215 newsrv->observe = HANA_OBS_LAYER7;
4216 }
4217 else {
4218 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004219 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004220 file, linenum, args[cur_arg], args[cur_arg + 1]);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223 }
4224
4225 cur_arg += 2;
4226 }
4227 else if (!strcmp(args[cur_arg], "on-error")) {
4228 if (!strcmp(args[cur_arg + 1], "fastinter"))
4229 newsrv->onerror = HANA_ONERR_FASTINTER;
4230 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4231 newsrv->onerror = HANA_ONERR_FAILCHK;
4232 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4233 newsrv->onerror = HANA_ONERR_SUDDTH;
4234 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4235 newsrv->onerror = HANA_ONERR_MARKDWN;
4236 else {
4237 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004238 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004239 file, linenum, args[cur_arg], args[cur_arg + 1]);
4240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
4242 }
4243
4244 cur_arg += 2;
4245 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004246 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4247 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4248 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4249 else {
4250 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4251 file, linenum, args[cur_arg], args[cur_arg + 1]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255
4256 cur_arg += 2;
4257 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004258 else if (!strcmp(args[cur_arg], "error-limit")) {
4259 if (!*args[cur_arg + 1]) {
4260 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4261 file, linenum, args[cur_arg]);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265
4266 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4267
4268 if (newsrv->consecutive_errors_limit <= 0) {
4269 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4270 file, linenum, args[cur_arg]);
4271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
4273 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004274 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004275 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004276 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004277 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004278 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004279
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004281#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004282 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004283 file, linenum, "source", "usesrc");
4284#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004285 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004287#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 }
4291 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004292 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4293 if (!sk) {
4294 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4295 err_code |= ERR_ALERT | ERR_FATAL;
4296 goto out;
4297 }
4298 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004299
4300 if (port_low != port_high) {
4301 int i;
4302 if (port_low <= 0 || port_low > 65535 ||
4303 port_high <= 0 || port_high > 65535 ||
4304 port_low > port_high) {
4305 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4306 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004309 }
4310 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4311 for (i = 0; i < newsrv->sport_range->size; i++)
4312 newsrv->sport_range->ports[i] = port_low + i;
4313 }
4314
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004316 while (*(args[cur_arg])) {
4317 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004318#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4319#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004320 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4321 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4322 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004326#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004327 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004328 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004329 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004330 err_code |= ERR_ALERT | ERR_FATAL;
4331 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004332 }
4333 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004334 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004335 newsrv->state |= SRV_TPROXY_CLI;
4336 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004337 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004338 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004339 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4340 char *name, *end;
4341
4342 name = args[cur_arg+1] + 7;
4343 while (isspace(*name))
4344 name++;
4345
4346 end = name;
4347 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4348 end++;
4349
4350 newsrv->state &= ~SRV_TPROXY_MASK;
4351 newsrv->state |= SRV_TPROXY_DYN;
4352 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4353 newsrv->bind_hdr_len = end - name;
4354 memcpy(newsrv->bind_hdr_name, name, end - name);
4355 newsrv->bind_hdr_name[end-name] = '\0';
4356 newsrv->bind_hdr_occ = -1;
4357
4358 /* now look for an occurrence number */
4359 while (isspace(*end))
4360 end++;
4361 if (*end == ',') {
4362 end++;
4363 name = end;
4364 if (*end == '-')
4365 end++;
4366 while (isdigit(*end))
4367 end++;
4368 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4369 }
4370
4371 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4372 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4373 " occurrences values smaller than %d.\n",
4374 file, linenum, MAX_HDR_HISTORY);
4375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
4377 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004378 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004379 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004380 if (!sk) {
4381 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
4384 }
4385 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004387 }
4388 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004389#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004390 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004391#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004392 cur_arg += 2;
4393 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004394#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004396 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004399#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4400 } /* "usesrc" */
4401
4402 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4403#ifdef SO_BINDTODEVICE
4404 if (!*args[cur_arg + 1]) {
4405 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4406 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004409 }
4410 if (newsrv->iface_name)
4411 free(newsrv->iface_name);
4412
4413 newsrv->iface_name = strdup(args[cur_arg + 1]);
4414 newsrv->iface_len = strlen(newsrv->iface_name);
4415 global.last_checks |= LSTCHK_NETADM;
4416#else
4417 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4418 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004419 err_code |= ERR_ALERT | ERR_FATAL;
4420 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004421#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004422 cur_arg += 2;
4423 continue;
4424 }
4425 /* this keyword in not an option of "source" */
4426 break;
4427 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004429 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004430 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4431 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004432 err_code |= ERR_ALERT | ERR_FATAL;
4433 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004436 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004437 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 +01004438 file, linenum, newsrv->id);
4439 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004440 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 +01004441 file, linenum);
4442
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 }
4446 }
4447
4448 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004449 if (newsrv->trackit) {
4450 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4451 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004454 }
4455
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004456 /* try to get the port from check_addr if check_port not set */
4457 if (!newsrv->check_port)
4458 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004459
Willy Tarreaubaaee002006-06-26 02:48:02 +02004460 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4461 newsrv->check_port = realport; /* by default */
4462 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004463 /* not yet valid, because no port was set on
4464 * the server either. We'll check if we have
4465 * a known port on the first listener.
4466 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004467 struct listener *l = curproxy->listen;
4468 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4469 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004470 }
4471 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004472 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4473 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004474 err_code |= ERR_ALERT | ERR_FATAL;
4475 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004476 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004477
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004478 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004479 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004480 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4481 err_code |= ERR_ALERT | ERR_ABORT;
4482 goto out;
4483 }
4484
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004485 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 newsrv->state |= SRV_CHECKED;
4487 }
4488
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004489 if (!defsrv) {
4490 if (newsrv->state & SRV_BACKUP)
4491 curproxy->srv_bck++;
4492 else
4493 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004494
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004495 newsrv->prev_state = newsrv->state;
4496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497 }
4498 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004499 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 int facility;
4501
4502 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4503 curproxy->logfac1 = global.logfac1;
4504 curproxy->logsrv1 = global.logsrv1;
4505 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004506 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004507 curproxy->logfac2 = global.logfac2;
4508 curproxy->logsrv2 = global.logsrv2;
4509 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004510 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 }
4512 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004513 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514
4515 facility = get_log_facility(args[2]);
4516 if (facility < 0) {
4517 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4518 exit(1);
4519 }
4520
4521 level = 7; /* max syslog level = debug */
4522 if (*(args[3])) {
4523 level = get_log_level(args[3]);
4524 if (level < 0) {
4525 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4526 exit(1);
4527 }
4528 }
4529
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004530 minlvl = 0; /* limit syslog level to this level (emerg) */
4531 if (*(args[4])) {
4532 minlvl = get_log_level(args[4]);
4533 if (level < 0) {
4534 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4535 exit(1);
4536 }
4537 }
4538
Robert Tsai81ae1952007-12-05 10:47:29 +01004539 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004540 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004541 if (!sk) {
4542 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004543 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004544 err_code |= ERR_ALERT | ERR_FATAL;
4545 goto out;
4546 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004547 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004548 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004549 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004550 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004551 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004555 logsrv.addr = *sk;
4556 if (!get_host_port(&logsrv.addr))
4557 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004559
4560 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004561 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004562 curproxy->logfac1 = facility;
4563 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004564 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565 }
4566 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004567 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 curproxy->logfac2 = facility;
4569 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004570 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 }
4572 else {
4573 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 }
4577 }
4578 else {
4579 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4580 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
4584 }
4585 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004586 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004587 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004588
Willy Tarreau977b8e42006-12-29 14:19:17 +01004589 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004591
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004593 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4594 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004597 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004598
4599 /* we must first clear any optional default setting */
4600 curproxy->options &= ~PR_O_TPXY_MASK;
4601 free(curproxy->iface_name);
4602 curproxy->iface_name = NULL;
4603 curproxy->iface_len = 0;
4604
Willy Tarreaud5191e72010-02-09 20:50:45 +01004605 sk = str2sa(args[1]);
4606 if (!sk) {
4607 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
4611 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004613
4614 cur_arg = 2;
4615 while (*(args[cur_arg])) {
4616 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004617#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4618#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004619 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4620 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4621 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004624 }
4625#endif
4626 if (!*args[cur_arg + 1]) {
4627 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4628 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004631 }
4632
4633 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004634 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004635 curproxy->options |= PR_O_TPXY_CLI;
4636 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004637 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004638 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004639 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4640 char *name, *end;
4641
4642 name = args[cur_arg+1] + 7;
4643 while (isspace(*name))
4644 name++;
4645
4646 end = name;
4647 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4648 end++;
4649
4650 curproxy->options &= ~PR_O_TPXY_MASK;
4651 curproxy->options |= PR_O_TPXY_DYN;
4652 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4653 curproxy->bind_hdr_len = end - name;
4654 memcpy(curproxy->bind_hdr_name, name, end - name);
4655 curproxy->bind_hdr_name[end-name] = '\0';
4656 curproxy->bind_hdr_occ = -1;
4657
4658 /* now look for an occurrence number */
4659 while (isspace(*end))
4660 end++;
4661 if (*end == ',') {
4662 end++;
4663 name = end;
4664 if (*end == '-')
4665 end++;
4666 while (isdigit(*end))
4667 end++;
4668 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4669 }
4670
4671 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4672 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4673 " occurrences values smaller than %d.\n",
4674 file, linenum, MAX_HDR_HISTORY);
4675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
4677 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004678 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004679 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004680 if (!sk) {
4681 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4682 err_code |= ERR_ALERT | ERR_FATAL;
4683 goto out;
4684 }
4685 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004686 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004687 }
4688 global.last_checks |= LSTCHK_NETADM;
4689#if !defined(CONFIG_HAP_LINUX_TPROXY)
4690 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004691#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004692#else /* no TPROXY support */
4693 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004694 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004697#endif
4698 cur_arg += 2;
4699 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004700 }
4701
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004702 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4703#ifdef SO_BINDTODEVICE
4704 if (!*args[cur_arg + 1]) {
4705 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4706 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004709 }
4710 if (curproxy->iface_name)
4711 free(curproxy->iface_name);
4712
4713 curproxy->iface_name = strdup(args[cur_arg + 1]);
4714 curproxy->iface_len = strlen(curproxy->iface_name);
4715 global.last_checks |= LSTCHK_NETADM;
4716#else
4717 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4718 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004721#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004722 cur_arg += 2;
4723 continue;
4724 }
4725 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4726 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004730 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004731 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4732 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4733 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004738 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004741 err_code |= ERR_ALERT | ERR_FATAL;
4742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004744
4745 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4746 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004747 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004748 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 }
4751 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004752 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4753 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004754 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004755 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
4758 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004759 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4760 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004761 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004762 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004764 }
4765 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4767 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004768 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004771 }
4772 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4774 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004778 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004779 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4781 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004784 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004785 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004786 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4788 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004789 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004791 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004792 }
4793 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4795 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004796 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004798 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004800 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004801 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004802 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4803 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004804 err_code |= ERR_ALERT | ERR_FATAL;
4805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004807
4808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4809 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004810 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 }
4814 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4816 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004817 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004818 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
4821 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004822 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4823 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004824 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004827 }
4828 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004829 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4830 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004831 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004834 }
4835 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4837 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004838 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004839 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004842 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004843 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4844 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004845 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004846 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004847 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004848 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004850 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004851
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 if (curproxy == &defproxy) {
4853 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004854 err_code |= ERR_ALERT | ERR_FATAL;
4855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004857 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004859
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 if (*(args[1]) == 0) {
4861 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004862 err_code |= ERR_ALERT | ERR_FATAL;
4863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004865
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004866 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4867 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4868 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4869 file, linenum, args[0]);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
4873 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4874 }
4875 else if (*args[2]) {
4876 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4877 file, linenum, args[0], args[2]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
4881
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004882 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004883 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004884 wl->s = strdup(args[1]);
4885 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004886 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 }
4888 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004889 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4891 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004895
Willy Tarreauade5ec42010-01-28 19:33:49 +01004896 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4897 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004898 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004899 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
4902 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004903 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4904 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004905 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004906 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004908 }
4909 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4911 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004912 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004913 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004915 }
4916 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4919 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 }
4923
Willy Tarreauade5ec42010-01-28 19:33:49 +01004924 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4925 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004926 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004927 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
4930 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4932 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004933 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004934 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
4937 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004938 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4939 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004940 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
4944 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004945 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004946
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 if (curproxy == &defproxy) {
4948 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004952 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 if (*(args[1]) == 0) {
4956 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004961 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4962 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4963 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4964 file, linenum, args[0]);
4965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
4967 }
4968 err_code |= warnif_cond_requires_req(cond, file, linenum);
4969 }
4970 else if (*args[2]) {
4971 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4972 file, linenum, args[0], args[2]);
4973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975 }
4976
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004977 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004978 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004979 wl->s = strdup(args[1]);
4980 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
4982 else if (!strcmp(args[0], "errorloc") ||
4983 !strcmp(args[0], "errorloc302") ||
4984 !strcmp(args[0], "errorloc303")) { /* error location */
4985 int errnum, errlen;
4986 char *err;
4987
Willy Tarreau977b8e42006-12-29 14:19:17 +01004988 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004989 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004990
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004992 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
4996
4997 errnum = atol(args[1]);
4998 if (!strcmp(args[0], "errorloc303")) {
4999 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5000 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5001 } else {
5002 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5003 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5004 }
5005
Willy Tarreau0f772532006-12-23 20:51:41 +01005006 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5007 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005008 chunk_destroy(&curproxy->errmsg[rc]);
5009 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005010 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005013
5014 if (rc >= HTTP_ERR_SIZE) {
5015 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5016 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 free(err);
5018 }
5019 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005020 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5021 int errnum, errlen, fd;
5022 char *err;
5023 struct stat stat;
5024
5025 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005027
5028 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005029 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005032 }
5033
5034 fd = open(args[2], O_RDONLY);
5035 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5036 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5037 file, linenum, args[2], args[1]);
5038 if (fd >= 0)
5039 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005042 }
5043
Willy Tarreau27a674e2009-08-17 07:23:33 +02005044 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005045 errlen = stat.st_size;
5046 } else {
5047 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005048 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005049 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005050 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005051 }
5052
5053 err = malloc(errlen); /* malloc() must succeed during parsing */
5054 errnum = read(fd, err, errlen);
5055 if (errnum != errlen) {
5056 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5057 file, linenum, args[2], args[1]);
5058 close(fd);
5059 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005062 }
5063 close(fd);
5064
5065 errnum = atol(args[1]);
5066 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5067 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005068 chunk_destroy(&curproxy->errmsg[rc]);
5069 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005070 break;
5071 }
5072 }
5073
5074 if (rc >= HTTP_ERR_SIZE) {
5075 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5076 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005077 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005078 free(err);
5079 }
5080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005082 struct cfg_kw_list *kwl;
5083 int index;
5084
5085 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5086 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5087 if (kwl->kw[index].section != CFG_LISTEN)
5088 continue;
5089 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5090 /* prepare error message just in case */
5091 snprintf(trash, sizeof(trash),
5092 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005093 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5094 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005095 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005098 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005099 else if (rc > 0) {
5100 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_WARN;
5102 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005103 }
Willy Tarreau93893792009-07-23 13:19:11 +02005104 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005105 }
5106 }
5107 }
5108
Willy Tarreau6daf3432008-01-22 16:44:08 +01005109 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005112 }
Willy Tarreau93893792009-07-23 13:19:11 +02005113 out:
5114 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115}
5116
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005117int
5118cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5119{
5120
5121 int err_code = 0;
5122 const char *err;
5123
5124 if (!strcmp(args[0], "userlist")) { /* new userlist */
5125 struct userlist *newul;
5126
5127 if (!*args[1]) {
5128 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5129 file, linenum, args[0]);
5130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
5132 }
5133
5134 err = invalid_char(args[1]);
5135 if (err) {
5136 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5137 file, linenum, *err, args[0], args[1]);
5138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
5140 }
5141
5142 for (newul = userlist; newul; newul = newul->next)
5143 if (!strcmp(newul->name, args[1])) {
5144 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5145 file, linenum, args[1]);
5146 err_code |= ERR_WARN;
5147 goto out;
5148 }
5149
5150 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5151 if (!newul) {
5152 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5153 err_code |= ERR_ALERT | ERR_ABORT;
5154 goto out;
5155 }
5156
5157 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5158 newul->name = strdup(args[1]);
5159
5160 if (!newul->groupusers | !newul->name) {
5161 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5162 err_code |= ERR_ALERT | ERR_ABORT;
5163 goto out;
5164 }
5165
5166 newul->next = userlist;
5167 userlist = newul;
5168
5169 } else if (!strcmp(args[0], "group")) { /* new group */
5170 int cur_arg, i;
5171 const char *err;
5172
5173 if (!*args[1]) {
5174 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5175 file, linenum, args[0]);
5176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
5178 }
5179
5180 err = invalid_char(args[1]);
5181 if (err) {
5182 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5183 file, linenum, *err, args[0], args[1]);
5184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
5186 }
5187
5188 for(i = 0; i < userlist->grpcnt; i++)
5189 if (!strcmp(userlist->groups[i], args[1])) {
5190 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5191 file, linenum, args[1], userlist->name);
5192 err_code |= ERR_ALERT;
5193 goto out;
5194 }
5195
5196 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5197 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5198 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
5201 }
5202
5203 cur_arg = 2;
5204
5205 while (*args[cur_arg]) {
5206 if (!strcmp(args[cur_arg], "users")) {
5207 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5208 cur_arg += 2;
5209 continue;
5210 } else {
5211 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5212 file, linenum, args[0]);
5213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
5216 }
5217
5218 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5219 } else if (!strcmp(args[0], "user")) { /* new user */
5220 struct auth_users *newuser;
5221 int cur_arg;
5222
5223 if (!*args[1]) {
5224 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5225 file, linenum, args[0]);
5226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
5228 }
5229
5230 for (newuser = userlist->users; newuser; newuser = newuser->next)
5231 if (!strcmp(newuser->user, args[1])) {
5232 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5233 file, linenum, args[1], userlist->name);
5234 err_code |= ERR_ALERT;
5235 goto out;
5236 }
5237
5238 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5239 if (!newuser) {
5240 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5241 err_code |= ERR_ALERT | ERR_ABORT;
5242 goto out;
5243 }
5244
5245 newuser->user = strdup(args[1]);
5246
5247 newuser->next = userlist->users;
5248 userlist->users = newuser;
5249
5250 cur_arg = 2;
5251
5252 while (*args[cur_arg]) {
5253 if (!strcmp(args[cur_arg], "password")) {
5254#ifndef CONFIG_HAP_CRYPT
5255 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5256 file, linenum);
5257 err_code |= ERR_ALERT;
5258#endif
5259 newuser->pass = strdup(args[cur_arg + 1]);
5260 cur_arg += 2;
5261 continue;
5262 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5263 newuser->pass = strdup(args[cur_arg + 1]);
5264 newuser->flags |= AU_O_INSECURE;
5265 cur_arg += 2;
5266 continue;
5267 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005268 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005269 cur_arg += 2;
5270 continue;
5271 } else {
5272 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5273 file, linenum, args[0]);
5274 err_code |= ERR_ALERT | ERR_FATAL;
5275 goto out;
5276 }
5277 }
5278 } else {
5279 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5280 err_code |= ERR_ALERT | ERR_FATAL;
5281 }
5282
5283out:
5284 return err_code;
5285}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005286
5287/*
5288 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005289 * Returns the error code, 0 if OK, or any combination of :
5290 * - ERR_ABORT: must abort ASAP
5291 * - ERR_FATAL: we can continue parsing but not start the service
5292 * - ERR_WARN: a warning has been emitted
5293 * - ERR_ALERT: an alert has been emitted
5294 * Only the two first ones can stop processing, the two others are just
5295 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005297int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005299 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 FILE *f;
5301 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005303 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 if ((f=fopen(file,"r")) == NULL)
5306 return -1;
5307
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005308 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005309 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005310 char *end;
5311 char *args[MAX_LINE_ARGS + 1];
5312 char *line = thisline;
5313
Willy Tarreaubaaee002006-06-26 02:48:02 +02005314 linenum++;
5315
5316 end = line + strlen(line);
5317
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005318 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5319 /* Check if we reached the limit and the last char is not \n.
5320 * Watch out for the last line without the terminating '\n'!
5321 */
5322 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005323 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005324 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005325 }
5326
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005328 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005329 line++;
5330
5331 arg = 0;
5332 args[arg] = line;
5333
5334 while (*line && arg < MAX_LINE_ARGS) {
5335 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5336 * C equivalent value. Other combinations left unchanged (eg: \1).
5337 */
5338 if (*line == '\\') {
5339 int skip = 0;
5340 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5341 *line = line[1];
5342 skip = 1;
5343 }
5344 else if (line[1] == 'r') {
5345 *line = '\r';
5346 skip = 1;
5347 }
5348 else if (line[1] == 'n') {
5349 *line = '\n';
5350 skip = 1;
5351 }
5352 else if (line[1] == 't') {
5353 *line = '\t';
5354 skip = 1;
5355 }
5356 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005357 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005358 unsigned char hex1, hex2;
5359 hex1 = toupper(line[2]) - '0';
5360 hex2 = toupper(line[3]) - '0';
5361 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5362 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5363 *line = (hex1<<4) + hex2;
5364 skip = 3;
5365 }
5366 else {
5367 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005368 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 }
5370 }
5371 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005372 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 end -= skip;
5374 }
5375 line++;
5376 }
5377 else if (*line == '#' || *line == '\n' || *line == '\r') {
5378 /* end of string, end of loop */
5379 *line = 0;
5380 break;
5381 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005382 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005384 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005385 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 line++;
5387 args[++arg] = line;
5388 }
5389 else {
5390 line++;
5391 }
5392 }
5393
5394 /* empty line */
5395 if (!**args)
5396 continue;
5397
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005398 if (*line) {
5399 /* we had to stop due to too many args.
5400 * Let's terminate the string, print the offending part then cut the
5401 * last arg.
5402 */
5403 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5404 line++;
5405 *line = '\0';
5406
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005407 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005408 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 args[arg] = line;
5411 }
5412
Willy Tarreau540abe42007-05-02 20:50:16 +02005413 /* zero out remaining args and ensure that at least one entry
5414 * is zeroed out.
5415 */
5416 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417 args[arg] = line;
5418 }
5419
Willy Tarreau3842f002009-06-14 11:39:52 +02005420 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005421 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005422 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005423 for (arg=0; *args[arg+1]; arg++)
5424 args[arg] = args[arg+1]; // shift args after inversion
5425 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005426 else if (!strcmp(args[0], "default")) {
5427 kwm = KWM_DEF;
5428 for (arg=0; *args[arg+1]; arg++)
5429 args[arg] = args[arg+1]; // shift args after inversion
5430 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005431
Willy Tarreau3842f002009-06-14 11:39:52 +02005432 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5433 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005434 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005435 }
5436
Willy Tarreau977b8e42006-12-29 14:19:17 +01005437 if (!strcmp(args[0], "listen") ||
5438 !strcmp(args[0], "frontend") ||
5439 !strcmp(args[0], "backend") ||
5440 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005441 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005443 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005444 cursection = strdup(args[0]);
5445 }
5446 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005448 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005449 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005450 }
5451 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005452 confsect = CFG_USERLIST;
5453 free(cursection);
5454 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005455 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005456 else if (!strcmp(args[0], "peers")) {
5457 confsect = CFG_PEERS;
5458 free(cursection);
5459 cursection = strdup(args[0]);
5460 }
5461
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 /* else it's a section keyword */
5463
5464 switch (confsect) {
5465 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005466 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 break;
5468 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005469 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005470 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005471 case CFG_USERLIST:
5472 err_code |= cfg_parse_users(file, linenum, args, kwm);
5473 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005474 case CFG_PEERS:
5475 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5476 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005478 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005479 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005481
5482 if (err_code & ERR_ABORT)
5483 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005484 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005485 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005486 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005488 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005489}
5490
Willy Tarreaubb925012009-07-23 13:36:36 +02005491/*
5492 * Returns the error code, 0 if OK, or any combination of :
5493 * - ERR_ABORT: must abort ASAP
5494 * - ERR_FATAL: we can continue parsing but not start the service
5495 * - ERR_WARN: a warning has been emitted
5496 * - ERR_ALERT: an alert has been emitted
5497 * Only the two first ones can stop processing, the two others are just
5498 * indicators.
5499 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005500int check_config_validity()
5501{
5502 int cfgerr = 0;
5503 struct proxy *curproxy = NULL;
5504 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005505 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005506 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005507 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508
5509 /*
5510 * Now, check for the integrity of all that we have collected.
5511 */
5512
5513 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005514 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005516 /* first, we will invert the proxy list order */
5517 curproxy = NULL;
5518 while (proxy) {
5519 struct proxy *next;
5520
5521 next = proxy->next;
5522 proxy->next = curproxy;
5523 curproxy = proxy;
5524 if (!next)
5525 break;
5526 proxy = next;
5527 }
5528
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005530 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005533 }
5534
5535 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005536 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005537 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005538 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005539 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005540 unsigned int next_id;
5541
5542 if (!curproxy->uuid) {
5543 /* proxy ID not set, use automatic numbering with first
5544 * spare entry starting with next_pxid.
5545 */
5546 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5547 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5548 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005549 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005550 next_pxid++;
5551
Willy Tarreau55ea7572007-06-17 19:56:27 +02005552
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005554 /* ensure we don't keep listeners uselessly bound */
5555 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556 curproxy = curproxy->next;
5557 continue;
5558 }
5559
Willy Tarreauff01a212009-03-15 13:46:16 +01005560 switch (curproxy->mode) {
5561 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005562 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005563 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005564 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5565 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005566 cfgerr++;
5567 }
5568
5569 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005570 Warning("config : servers will be ignored for %s '%s'.\n",
5571 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005572 break;
5573
5574 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005575 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005576 break;
5577
5578 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005579 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005580 break;
5581 }
5582
5583 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005584 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5585 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 cfgerr++;
5587 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005588
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005589 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005590 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005591 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005592 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5593 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005594 cfgerr++;
5595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005597 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005598 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5599 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005600 cfgerr++;
5601 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005603 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005604 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5605 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005606 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005607 }
5608 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005609 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005610 /* If no LB algo is set in a backend, and we're not in
5611 * transparent mode, dispatch mode nor proxy mode, we
5612 * want to use balance roundrobin by default.
5613 */
5614 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5615 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 }
5617 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005618
Willy Tarreau1620ec32011-08-06 17:05:02 +02005619 if (curproxy->options & PR_O_DISPATCH)
5620 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5621 else if (curproxy->options & PR_O_HTTP_PROXY)
5622 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5623 else if (curproxy->options & PR_O_TRANSP)
5624 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005625
Willy Tarreau1620ec32011-08-06 17:05:02 +02005626 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5627 if (curproxy->options & PR_O_DISABLE404) {
5628 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5629 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5630 err_code |= ERR_WARN;
5631 curproxy->options &= ~PR_O_DISABLE404;
5632 }
5633 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5634 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5635 "send-state", proxy_type_str(curproxy), curproxy->id);
5636 err_code |= ERR_WARN;
5637 curproxy->options &= ~PR_O2_CHK_SNDST;
5638 }
Willy Tarreauef781042010-01-27 11:53:01 +01005639 }
5640
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005641 /* if a default backend was specified, let's find it */
5642 if (curproxy->defbe.name) {
5643 struct proxy *target;
5644
Alex Williams96532db2009-11-01 21:27:13 -05005645 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005646 if (!target) {
5647 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5648 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005649 cfgerr++;
5650 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005651 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5652 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005653 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005654 } else {
5655 free(curproxy->defbe.name);
5656 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005657 /* we force the backend to be present on at least all of
5658 * the frontend's processes.
5659 */
5660 target->bind_proc = curproxy->bind_proc ?
5661 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 }
5663 }
5664
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005665 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005666 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5667 /* map jump target for ACT_SETBE in req_rep chain */
5668 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005669 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005670 struct proxy *target;
5671
Willy Tarreaua496b602006-12-17 23:15:24 +01005672 if (exp->action != ACT_SETBE)
5673 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005674
Alex Williams96532db2009-11-01 21:27:13 -05005675 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005676 if (!target) {
5677 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5678 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005679 cfgerr++;
5680 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005681 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5682 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005683 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005684 } else {
5685 free((void *)exp->replace);
5686 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005687 /* we force the backend to be present on at least all of
5688 * the frontend's processes.
5689 */
5690 target->bind_proc = curproxy->bind_proc ?
5691 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005692 }
5693 }
5694 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005695
5696 /* find the target proxy for 'use_backend' rules */
5697 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005698 struct proxy *target;
5699
Alex Williams96532db2009-11-01 21:27:13 -05005700 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005701
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005702 if (!target) {
5703 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5704 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005705 cfgerr++;
5706 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005707 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5708 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005709 cfgerr++;
5710 } else {
5711 free((void *)rule->be.name);
5712 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005713 /* we force the backend to be present on at least all of
5714 * the frontend's processes.
5715 */
5716 target->bind_proc = curproxy->bind_proc ?
5717 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005718 }
5719 }
5720
Emeric Brunb982a3d2010-01-04 15:45:53 +01005721 /* find the target table for 'stick' rules */
5722 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5723 struct proxy *target;
5724
Emeric Brun1d33b292010-01-04 15:47:17 +01005725 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5726 if (mrule->flags & STK_IS_STORE)
5727 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5728
Emeric Brunb982a3d2010-01-04 15:45:53 +01005729 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005730 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005731 else
5732 target = curproxy;
5733
5734 if (!target) {
5735 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5736 curproxy->id, mrule->table.name);
5737 cfgerr++;
5738 }
5739 else if (target->table.size == 0) {
5740 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5741 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5742 cfgerr++;
5743 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005744 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005745 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5746 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5747 cfgerr++;
5748 }
5749 else {
5750 free((void *)mrule->table.name);
5751 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005752 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005753 }
5754 }
5755
5756 /* find the target table for 'store response' rules */
5757 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5758 struct proxy *target;
5759
Emeric Brun1d33b292010-01-04 15:47:17 +01005760 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5761
Emeric Brunb982a3d2010-01-04 15:45:53 +01005762 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005763 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005764 else
5765 target = curproxy;
5766
5767 if (!target) {
5768 Alert("Proxy '%s': unable to find store table '%s'.\n",
5769 curproxy->id, mrule->table.name);
5770 cfgerr++;
5771 }
5772 else if (target->table.size == 0) {
5773 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5774 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5775 cfgerr++;
5776 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005777 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005778 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5779 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5780 cfgerr++;
5781 }
5782 else {
5783 free((void *)mrule->table.name);
5784 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005785 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005786 }
5787 }
5788
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005789 /* find the target table for 'tcp-request' layer 4 rules */
5790 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5791 struct proxy *target;
5792
Willy Tarreau56123282010-08-06 19:06:56 +02005793 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005794 continue;
5795
5796 if (trule->act_prm.trk_ctr.table.n)
5797 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5798 else
5799 target = curproxy;
5800
5801 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005802 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5803 curproxy->id, trule->act_prm.trk_ctr.table.n,
5804 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005805 cfgerr++;
5806 }
5807 else if (target->table.size == 0) {
5808 Alert("Proxy '%s': table '%s' used but not configured.\n",
5809 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5810 cfgerr++;
5811 }
5812 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005813 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 +02005814 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5815 cfgerr++;
5816 }
5817 else {
5818 free(trule->act_prm.trk_ctr.table.n);
5819 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005820 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005821 * to pass a list of counters to track and allocate them right here using
5822 * stktable_alloc_data_type().
5823 */
5824 }
5825 }
5826
Willy Tarreaud1f96522010-08-03 19:34:32 +02005827 /* find the target table for 'tcp-request' layer 6 rules */
5828 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5829 struct proxy *target;
5830
Willy Tarreau56123282010-08-06 19:06:56 +02005831 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005832 continue;
5833
5834 if (trule->act_prm.trk_ctr.table.n)
5835 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5836 else
5837 target = curproxy;
5838
5839 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005840 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5841 curproxy->id, trule->act_prm.trk_ctr.table.n,
5842 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005843 cfgerr++;
5844 }
5845 else if (target->table.size == 0) {
5846 Alert("Proxy '%s': table '%s' used but not configured.\n",
5847 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5848 cfgerr++;
5849 }
5850 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005851 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 +02005852 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5853 cfgerr++;
5854 }
5855 else {
5856 free(trule->act_prm.trk_ctr.table.n);
5857 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005858 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005859 * to pass a list of counters to track and allocate them right here using
5860 * stktable_alloc_data_type().
5861 */
5862 }
5863 }
5864
Emeric Brun32da3c42010-09-23 18:39:19 +02005865 if (curproxy->table.peers.name) {
5866 struct peers *curpeers = peers;
5867
5868 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5869 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5870 free((void *)curproxy->table.peers.name);
5871 curproxy->table.peers.p = peers;
5872 break;
5873 }
5874 }
5875
5876 if (!curpeers) {
5877 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5878 curproxy->id, curproxy->table.peers.name);
5879 cfgerr++;
5880 }
5881 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005882 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5883 curproxy->id, localpeer, curpeers->id);
Emeric Brun32da3c42010-09-23 18:39:19 +02005884 cfgerr++;
5885 }
5886 }
5887
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005888 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005889 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005890 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5891 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5892 "proxy", curproxy->id);
5893 cfgerr++;
5894 goto out_uri_auth_compat;
5895 }
5896
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005897 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005898 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005899 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005900 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005901
Willy Tarreau95fa4692010-02-01 13:05:50 +01005902 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5903 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005904
5905 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005906 uri_auth_compat_req[i++] = "realm";
5907 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5908 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005909
Willy Tarreau95fa4692010-02-01 13:05:50 +01005910 uri_auth_compat_req[i++] = "unless";
5911 uri_auth_compat_req[i++] = "{";
5912 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5913 uri_auth_compat_req[i++] = "}";
5914 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005915
Willy Tarreauff011f22011-01-06 17:51:27 +01005916 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5917 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005918 cfgerr++;
5919 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005920 }
5921
Willy Tarreauff011f22011-01-06 17:51:27 +01005922 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005923
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005924 if (curproxy->uri_auth->auth_realm) {
5925 free(curproxy->uri_auth->auth_realm);
5926 curproxy->uri_auth->auth_realm = NULL;
5927 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005928
5929 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005930 }
5931out_uri_auth_compat:
5932
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005933 cfgerr += acl_find_targets(curproxy);
5934
Willy Tarreau2738a142006-07-08 17:28:09 +02005935 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005936 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005937 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005938 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005939 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005940 " | While not properly invalid, you will certainly encounter various problems\n"
5941 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005942 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005943 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005944 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005945 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005946
Willy Tarreau1fa31262007-12-03 00:36:16 +01005947 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5948 * We must still support older configurations, so let's find out whether those
5949 * parameters have been set or must be copied from contimeouts.
5950 */
5951 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005952 if (!curproxy->timeout.tarpit ||
5953 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005954 /* tarpit timeout not set. We search in the following order:
5955 * default.tarpit, curr.connect, default.connect.
5956 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005957 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005958 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005959 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005960 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005961 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005962 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005963 }
5964 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005965 (!curproxy->timeout.queue ||
5966 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005967 /* queue timeout not set. We search in the following order:
5968 * default.queue, curr.connect, default.connect.
5969 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005970 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005971 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005972 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005973 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005974 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005975 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005976 }
5977 }
5978
Willy Tarreau1620ec32011-08-06 17:05:02 +02005979 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005980 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5981 curproxy->check_req = (char *)malloc(curproxy->check_len);
5982 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005983 }
5984
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005985 /* The small pools required for the capture lists */
5986 if (curproxy->nb_req_cap)
5987 curproxy->req_cap_pool = create_pool("ptrcap",
5988 curproxy->nb_req_cap * sizeof(char *),
5989 MEM_F_SHARED);
5990 if (curproxy->nb_rsp_cap)
5991 curproxy->rsp_cap_pool = create_pool("ptrcap",
5992 curproxy->nb_rsp_cap * sizeof(char *),
5993 MEM_F_SHARED);
5994
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 /* first, we will invert the servers list order */
5996 newsrv = NULL;
5997 while (curproxy->srv) {
5998 struct server *next;
5999
6000 next = curproxy->srv->next;
6001 curproxy->srv->next = newsrv;
6002 newsrv = curproxy->srv;
6003 if (!next)
6004 break;
6005 curproxy->srv = next;
6006 }
6007
Willy Tarreaudd701652010-05-25 23:03:02 +02006008 /* assign automatic UIDs to servers which don't have one yet */
6009 next_id = 1;
6010 newsrv = curproxy->srv;
6011 while (newsrv != NULL) {
6012 if (!newsrv->puid) {
6013 /* server ID not set, use automatic numbering with first
6014 * spare entry starting with next_svid.
6015 */
6016 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6017 newsrv->conf.id.key = newsrv->puid = next_id;
6018 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6019 }
6020 next_id++;
6021 newsrv = newsrv->next;
6022 }
6023
Willy Tarreau20697042007-11-15 23:26:18 +01006024 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006025 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006027 /* We have to initialize the server lookup mechanism depending
6028 * on what LB algorithm was choosen.
6029 */
6030
6031 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6032 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6033 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006034 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6035 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6036 init_server_map(curproxy);
6037 } else {
6038 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6039 fwrr_init_server_groups(curproxy);
6040 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006041 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006042
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006043 case BE_LB_KIND_LC:
6044 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006045 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006046 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006047
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006048 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006049 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6050 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6051 chash_init_server_tree(curproxy);
6052 } else {
6053 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6054 init_server_map(curproxy);
6055 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006056 break;
6057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006058
6059 if (curproxy->options & PR_O_LOGASAP)
6060 curproxy->to_log &= ~LW_BYTES;
6061
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006062 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6063 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6064 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6065 proxy_type_str(curproxy), curproxy->id);
6066 err_code |= ERR_WARN;
6067 }
6068
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006069 if (curproxy->mode != PR_MODE_HTTP) {
6070 int optnum;
6071
6072 if (curproxy->options & PR_O_COOK_ANY) {
6073 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6074 proxy_type_str(curproxy), curproxy->id);
6075 err_code |= ERR_WARN;
6076 }
6077
6078 if (curproxy->uri_auth) {
6079 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6080 proxy_type_str(curproxy), curproxy->id);
6081 err_code |= ERR_WARN;
6082 curproxy->uri_auth = NULL;
6083 }
6084
Willy Tarreau87cf5142011-08-19 22:57:24 +02006085 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006086 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6087 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6088 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006089 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006090 }
6091
6092 if (curproxy->options & PR_O_ORGTO) {
6093 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6094 "originalto", proxy_type_str(curproxy), curproxy->id);
6095 err_code |= ERR_WARN;
6096 curproxy->options &= ~PR_O_ORGTO;
6097 }
6098
6099 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6100 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6101 (curproxy->cap & cfg_opts[optnum].cap) &&
6102 (curproxy->options & cfg_opts[optnum].val)) {
6103 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6104 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6105 err_code |= ERR_WARN;
6106 curproxy->options &= ~cfg_opts[optnum].val;
6107 }
6108 }
6109
6110 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6111 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6112 (curproxy->cap & cfg_opts2[optnum].cap) &&
6113 (curproxy->options2 & cfg_opts2[optnum].val)) {
6114 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6115 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6116 err_code |= ERR_WARN;
6117 curproxy->options2 &= ~cfg_opts2[optnum].val;
6118 }
6119 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006120
Willy Tarreauefa5f512010-03-30 20:13:29 +02006121#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006122 if (curproxy->bind_hdr_occ) {
6123 curproxy->bind_hdr_occ = 0;
6124 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6125 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6126 err_code |= ERR_WARN;
6127 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006128#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006129 }
6130
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006132 * ensure that we're not cross-dressing a TCP server into HTTP.
6133 */
6134 newsrv = curproxy->srv;
6135 while (newsrv != NULL) {
6136 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006137 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6138 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006139 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006140 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006141
Willy Tarreauefa5f512010-03-30 20:13:29 +02006142#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006143 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6144 newsrv->bind_hdr_occ = 0;
6145 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6146 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6147 err_code |= ERR_WARN;
6148 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006149#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006150 newsrv = newsrv->next;
6151 }
6152
6153 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154 * If this server supports a maxconn parameter, it needs a dedicated
6155 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006156 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 */
6158 newsrv = curproxy->srv;
6159 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006160 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 /* Only 'minconn' was specified, or it was higher than or equal
6162 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6163 * this will avoid further useless expensive computations.
6164 */
6165 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006166 } else if (newsrv->maxconn && !newsrv->minconn) {
6167 /* minconn was not specified, so we set it to maxconn */
6168 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169 }
6170
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006171 if (newsrv->trackit) {
6172 struct proxy *px;
6173 struct server *srv;
6174 char *pname, *sname;
6175
6176 pname = newsrv->trackit;
6177 sname = strrchr(pname, '/');
6178
6179 if (sname)
6180 *sname++ = '\0';
6181 else {
6182 sname = pname;
6183 pname = NULL;
6184 }
6185
6186 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006187 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006188 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006189 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6190 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006191 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006192 cfgerr++;
6193 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006194 }
6195 } else
6196 px = curproxy;
6197
6198 srv = findserver(px, sname);
6199 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006200 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6201 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006202 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006203 cfgerr++;
6204 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006205 }
6206
6207 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006208 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006209 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006210 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006211 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006212 cfgerr++;
6213 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006214 }
6215
6216 if (curproxy != px &&
6217 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006218 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006219 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006220 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006221 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006222 cfgerr++;
6223 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006224 }
6225
6226 newsrv->tracked = srv;
6227 newsrv->tracknext = srv->tracknext;
6228 srv->tracknext = newsrv;
6229
6230 free(newsrv->trackit);
6231 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006232 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 newsrv = newsrv->next;
6234 }
6235
Willy Tarreauc1a21672009-08-16 22:37:44 +02006236 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006237 curproxy->accept = frontend_accept;
6238
Willy Tarreauc1a21672009-08-16 22:37:44 +02006239 if (curproxy->tcp_req.inspect_delay ||
6240 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006241 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006242
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006243 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006244 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006245 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006246 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006247
6248 /* both TCP and HTTP must check switching rules */
6249 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6250 }
6251
6252 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006253 if (curproxy->tcp_req.inspect_delay ||
6254 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6255 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6256
Emeric Brun97679e72010-09-23 17:56:44 +02006257 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6258 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6259
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006260 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006261 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006262 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006263 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006264
6265 /* If the backend does requires RDP cookie persistence, we have to
6266 * enable the corresponding analyser.
6267 */
6268 if (curproxy->options2 & PR_O2_RDPC_PRST)
6269 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6270 }
6271
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006272 listener = NULL;
6273 while (curproxy->listen) {
6274 struct listener *next;
6275
6276 next = curproxy->listen->next;
6277 curproxy->listen->next = listener;
6278 listener = curproxy->listen;
6279
6280 if (!next)
6281 break;
6282
6283 curproxy->listen = next;
6284 }
6285
Willy Tarreaue6b98942007-10-29 01:09:36 +01006286 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006287 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006288 listener = curproxy->listen;
6289 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006290 if (!listener->luid) {
6291 /* listener ID not set, use automatic numbering with first
6292 * spare entry starting with next_luid.
6293 */
6294 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6295 listener->conf.id.key = listener->luid = next_id;
6296 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006297 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006298 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006299
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006300 /* enable separate counters */
6301 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6302 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6303 if (!listener->name) {
6304 sprintf(trash, "sock-%d", listener->luid);
6305 listener->name = strdup(trash);
6306 }
6307 }
6308
Willy Tarreaue6b98942007-10-29 01:09:36 +01006309 if (curproxy->options & PR_O_TCP_NOLING)
6310 listener->options |= LI_O_NOLINGER;
6311 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006312 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006313 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006314 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006315 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006316 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006317 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006318
Willy Tarreau8a956912010-10-15 14:27:08 +02006319 if (listener->options & LI_O_ACC_PROXY)
6320 listener->analysers |= AN_REQ_DECODE_PROXY;
6321
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006322 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6323 listener->options |= LI_O_TCP_RULES;
6324
Willy Tarreaude3041d2010-05-31 10:56:17 +02006325 if (curproxy->mon_mask.s_addr)
6326 listener->options |= LI_O_CHK_MONNET;
6327
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006328 /* smart accept mode is automatic in HTTP mode */
6329 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6330 (curproxy->mode == PR_MODE_HTTP &&
6331 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6332 listener->options |= LI_O_NOQUICKACK;
6333
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006334 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006335 listener = listener->next;
6336 }
6337
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006338 /* Check multi-process mode compatibility for the current proxy */
6339 if (global.nbproc > 1) {
6340 int nbproc = 0;
6341 if (curproxy->bind_proc) {
6342 int proc;
6343 for (proc = 0; proc < global.nbproc; proc++) {
6344 if (curproxy->bind_proc & (1 << proc)) {
6345 nbproc++;
6346 }
6347 }
6348 } else {
6349 nbproc = global.nbproc;
6350 }
6351 if (curproxy->table.peers.name) {
6352 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6353 curproxy->id);
6354 cfgerr++;
6355 }
6356 if (nbproc > 1) {
6357 if (curproxy->uri_auth) {
6358 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6359 curproxy->id);
6360 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6361 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6362 curproxy->id);
6363 }
6364 }
6365 if (curproxy->appsession_name) {
6366 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6367 curproxy->id);
6368 }
6369 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6370 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6371 curproxy->id);
6372 }
6373 }
6374 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006375
6376 /* create the task associated with the proxy */
6377 curproxy->task = task_new();
6378 if (curproxy->task) {
6379 curproxy->task->context = curproxy;
6380 curproxy->task->process = manage_proxy;
6381 /* no need to queue, it will be done automatically if some
6382 * listener gets limited.
6383 */
6384 curproxy->task->expire = TICK_ETERNITY;
6385 } else {
6386 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6387 curproxy->id);
6388 cfgerr++;
6389 }
6390
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 curproxy = curproxy->next;
6392 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006393
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006394 /* Check multi-process mode compatibility */
6395 if (global.nbproc > 1) {
6396 if (global.stats_fe) {
6397 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6398 }
6399 }
6400
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006401 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6402 struct auth_users *curuser;
6403 int g;
6404
6405 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6406 unsigned int group_mask = 0;
6407 char *group = NULL;
6408
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006409 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006410 continue;
6411
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006412 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006413
6414 for (g = 0; g < curuserlist->grpcnt; g++)
6415 if (!strcmp(curuserlist->groups[g], group))
6416 break;
6417
6418 if (g == curuserlist->grpcnt) {
6419 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6420 curuserlist->name, group, curuser->user);
6421 err_code |= ERR_ALERT | ERR_FATAL;
6422 goto out;
6423 }
6424
6425 group_mask |= (1 << g);
6426 }
6427
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006428 free(curuser->u.groups);
6429 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006430 }
6431
6432 for (g = 0; g < curuserlist->grpcnt; g++) {
6433 char *user = NULL;
6434
6435 if (!curuserlist->groupusers[g])
6436 continue;
6437
6438 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6439 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6440 if (!strcmp(curuser->user, user))
6441 break;
6442
6443 if (!curuser) {
6444 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6445 curuserlist->name, user, curuserlist->groups[g]);
6446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto out;
6448 }
6449
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006450 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006451 }
6452
6453 free(curuserlist->groupusers[g]);
6454 }
6455
6456 free(curuserlist->groupusers);
6457
6458#ifdef DEBUG_AUTH
6459 for (g = 0; g < curuserlist->grpcnt; g++) {
6460 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6461
6462 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6463 if (curuser->group_mask & (1 << g))
6464 fprintf(stderr, " %s", curuser->user);
6465 }
6466
6467 fprintf(stderr, "\n");
6468 }
6469#endif
6470
Willy Tarreaufbb78422011-06-05 15:38:35 +02006471 }
6472
6473 /* automatically compute fullconn if not set. We must not do it in the
6474 * loop above because cross-references are not yet fully resolved.
6475 */
6476 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6477 /* If <fullconn> is not set, let's set it to 10% of the sum of
6478 * the possible incoming frontend's maxconns.
6479 */
6480 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6481 struct proxy *fe;
6482 int total = 0;
6483
6484 /* sum up the number of maxconns of frontends which
6485 * reference this backend at least once or which are
6486 * the same one ('listen').
6487 */
6488 for (fe = proxy; fe; fe = fe->next) {
6489 struct switching_rule *rule;
6490 struct hdr_exp *exp;
6491 int found = 0;
6492
6493 if (!(fe->cap & PR_CAP_FE))
6494 continue;
6495
6496 if (fe == curproxy) /* we're on a "listen" instance */
6497 found = 1;
6498
6499 if (fe->defbe.be == curproxy) /* "default_backend" */
6500 found = 1;
6501
6502 /* check if a "use_backend" rule matches */
6503 if (!found) {
6504 list_for_each_entry(rule, &fe->switching_rules, list) {
6505 if (rule->be.backend == curproxy) {
6506 found = 1;
6507 break;
6508 }
6509 }
6510 }
6511
6512 /* check if a "reqsetbe" rule matches */
6513 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6514 if (exp->action == ACT_SETBE &&
6515 (struct proxy *)exp->replace == curproxy) {
6516 found = 1;
6517 break;
6518 }
6519 }
6520
6521 /* now we've checked all possible ways to reference a backend
6522 * from a frontend.
6523 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006524 if (!found)
6525 continue;
6526 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006527 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006528 /* we have the sum of the maxconns in <total>. We only
6529 * keep 10% of that sum to set the default fullconn, with
6530 * a hard minimum of 1 (to avoid a divide by zero).
6531 */
6532 curproxy->fullconn = (total + 9) / 10;
6533 if (!curproxy->fullconn)
6534 curproxy->fullconn = 1;
6535 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006536 }
6537
Willy Tarreau056f5682010-06-06 15:51:11 +02006538 /* initialize stick-tables on backend capable proxies. This must not
6539 * be done earlier because the data size may be discovered while parsing
6540 * other proxies.
6541 */
6542 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006543 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006544
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006545 /*
6546 * Recount currently required checks.
6547 */
6548
6549 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6550 int optnum;
6551
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006552 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6553 if (curproxy->options & cfg_opts[optnum].val)
6554 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006555
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006556 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6557 if (curproxy->options2 & cfg_opts2[optnum].val)
6558 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006559 }
6560
Willy Tarreau122541c2011-09-07 21:24:49 +02006561 if (peers) {
6562 struct peers *curpeers = peers, **last;
6563 struct peer *p, *pb;
6564
6565 /* Remove all peers sections which don't have a valid listener.
6566 * This can happen when a peers section is never referenced and
6567 * does not contain a local peer.
6568 */
6569 last = &peers;
6570 while (*last) {
6571 curpeers = *last;
6572 if (curpeers->peers_fe) {
6573 last = &curpeers->next;
6574 continue;
6575 }
6576
6577 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6578 curpeers->id, localpeer);
6579
6580 p = curpeers->remote;
6581 while (p) {
6582 pb = p->next;
6583 free(p->id);
6584 free(p);
6585 p = pb;
6586 }
6587
6588 /* Destroy and unlink this curpeers section.
6589 * Note: curpeers is backed up into *last.
6590 */
6591 free(curpeers->id);
6592 curpeers = curpeers->next;
6593 free(*last);
6594 *last = curpeers;
6595 }
6596 }
6597
Willy Tarreau34eb6712011-10-24 18:15:04 +02006598 pool2_hdr_idx = create_pool("hdr_idx",
6599 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6600 MEM_F_SHARED);
6601
Willy Tarreaubb925012009-07-23 13:36:36 +02006602 if (cfgerr > 0)
6603 err_code |= ERR_ALERT | ERR_FATAL;
6604 out:
6605 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606}
6607
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006608/*
6609 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6610 * parsing sessions.
6611 */
6612void cfg_register_keywords(struct cfg_kw_list *kwl)
6613{
6614 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6615}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006617/*
6618 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6619 */
6620void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6621{
6622 LIST_DEL(&kwl->list);
6623 LIST_INIT(&kwl->list);
6624}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006625
6626/*
6627 * Local variables:
6628 * c-indent-level: 8
6629 * c-basic-offset: 8
6630 * End:
6631 */