blob: b157934832086f641ae6654e46eaa81bdf80bc8d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200164 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100165 { NULL, 0, 0, 0 }
166};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167
Willy Tarreau6daf3432008-01-22 16:44:08 +0100168static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
170int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100171int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200173/* List head of all known configuration keywords */
174static struct cfg_kw_list cfg_keywords = {
175 .list = LIST_HEAD_INIT(cfg_keywords.list)
176};
177
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178/*
179 * converts <str> to a list of listeners which are dynamically allocated.
180 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
181 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
182 * - <port> is a numerical port from 1 to 65535 ;
183 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
184 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200185 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100187static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188{
189 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100190 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 int port, end;
192
193 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200194
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 while (next && *next) {
196 struct sockaddr_storage ss;
197
198 str = next;
199 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100200 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 *next++ = 0;
202 }
203
Emeric Bruned760922010-10-22 17:59:25 +0200204 if (*str == '/') {
205 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
206 /* so compute max path */
207 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
208 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209
Emeric Bruned760922010-10-22 17:59:25 +0200210 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
212 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200213 goto fail;
214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200217 ss.ss_family = AF_UNIX;
218 if (global.unix_bind.prefix) {
219 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
220 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 }
Emeric Bruned760922010-10-22 17:59:25 +0200222 else {
223 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
224 }
225 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 }
227 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 ss2 = str2sa_range(str, &port, &end);
231 if (!ss2) {
232 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
233 file, line, str);
234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 if (!port) {
238 Alert("parsing [%s:%d] : missing port number: '%s'\n",
239 file, line, str);
240 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100243 /* OK the address looks correct */
244 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Emeric Bruned760922010-10-22 17:59:25 +0200246 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
248 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
251
252 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
254 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257 }
258
259 for (; port <= end; port++) {
260 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200261 l->next = curproxy->listen;
262 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
264 l->fd = -1;
265 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100266 l->state = LI_INIT;
267
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100268 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100270 tcpv4_add_listener(l);
271 }
Emeric Bruned760922010-10-22 17:59:25 +0200272 else if (ss.ss_family == AF_INET6) {
273 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
274 tcpv6_add_listener(l);
275 }
276 else {
277 l->perm.ux.gid = l->perm.ux.uid = -1;
278 l->perm.ux.mode = 0;
279 uxst_add_listener(l);
280 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200281
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200282 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100283 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 } /* end for(port) */
285 } /* end while(next) */
286 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 fail:
289 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291}
292
Willy Tarreau977b8e42006-12-29 14:19:17 +0100293/*
294 * Sends a warning if proxy <proxy> does not have at least one of the
295 * capabilities in <cap>. An optionnal <hint> may be added at the end
296 * of the warning to help the user. Returns 1 if a warning was emitted
297 * or 0 if the condition is valid.
298 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100299int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100300{
301 char *msg;
302
303 switch (cap) {
304 case PR_CAP_BE: msg = "no backend"; break;
305 case PR_CAP_FE: msg = "no frontend"; break;
306 case PR_CAP_RS: msg = "no ruleset"; break;
307 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
308 default: msg = "not enough"; break;
309 }
310
311 if (!(proxy->cap & cap)) {
312 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100313 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100314 return 1;
315 }
316 return 0;
317}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318
Willy Tarreau61d18892009-03-31 10:49:21 +0200319/* Report a warning if a rule is placed after a 'block' rule.
320 * Return 1 if the warning has been emitted, otherwise 0.
321 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100322int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200323{
324 if (!LIST_ISEMPTY(&proxy->block_cond)) {
325 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
326 file, line, arg);
327 return 1;
328 }
329 return 0;
330}
331
332/* Report a warning if a rule is placed after a reqrewrite rule.
333 * Return 1 if the warning has been emitted, otherwise 0.
334 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100335int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200336{
337 if (proxy->req_exp) {
338 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
339 file, line, arg);
340 return 1;
341 }
342 return 0;
343}
344
345/* Report a warning if a rule is placed after a reqadd rule.
346 * Return 1 if the warning has been emitted, otherwise 0.
347 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100348int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200349{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100350 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200351 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
352 file, line, arg);
353 return 1;
354 }
355 return 0;
356}
357
358/* Report a warning if a rule is placed after a redirect rule.
359 * Return 1 if the warning has been emitted, otherwise 0.
360 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100361int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200362{
363 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
364 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
365 file, line, arg);
366 return 1;
367 }
368 return 0;
369}
370
371/* Report a warning if a rule is placed after a 'use_backend' rule.
372 * Return 1 if the warning has been emitted, otherwise 0.
373 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100374int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200375{
376 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
377 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
378 file, line, arg);
379 return 1;
380 }
381 return 0;
382}
383
384/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100385int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200386{
387 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
388 warnif_rule_after_reqadd(proxy, file, line, arg) ||
389 warnif_rule_after_redirect(proxy, file, line, arg) ||
390 warnif_rule_after_use_backend(proxy, file, line, arg);
391}
392
393/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
397 warnif_rule_after_redirect(proxy, file, line, arg) ||
398 warnif_rule_after_use_backend(proxy, file, line, arg);
399}
400
401/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 return warnif_rule_after_redirect(proxy, file, line, arg) ||
405 warnif_rule_after_use_backend(proxy, file, line, arg);
406}
407
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100408/* Report it if a request ACL condition uses some response-only parameters. It
409 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
410 * Note that <cond> may be NULL and then will be ignored.
411 */
412static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
413{
414 struct acl *acl;
415
416 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
417 return 0;
418
419 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
420 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
421 file, line, acl ? acl->name : "(unknown)");
422 return ERR_WARN;
423}
424
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100425/* Report it if a request ACL condition uses some request-only volatile parameters.
426 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
427 * Note that <cond> may be NULL and then will be ignored.
428 */
429static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
430{
431 struct acl *acl;
432
433 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
434 return 0;
435
436 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
437 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
438 file, line, acl ? acl->name : "(unknown)");
439 return ERR_WARN;
440}
441
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100442
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200444 * parse a line in a <global> section. Returns the error code, 0 if OK, or
445 * any combination of :
446 * - ERR_ABORT: must abort ASAP
447 * - ERR_FATAL: we can continue parsing but not start the service
448 * - ERR_WARN: a warning has been emitted
449 * - ERR_ALERT: an alert has been emitted
450 * Only the two first ones can stop processing, the two others are just
451 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200453int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454{
Willy Tarreau058e9072009-07-20 09:30:05 +0200455 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456
457 if (!strcmp(args[0], "global")) { /* new section */
458 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 }
461 else if (!strcmp(args[0], "daemon")) {
462 global.mode |= MODE_DAEMON;
463 }
464 else if (!strcmp(args[0], "debug")) {
465 global.mode |= MODE_DEBUG;
466 }
467 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100468 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200470 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100471 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200472 }
473 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100474 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100477 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100479 else if (!strcmp(args[0], "nosplice")) {
480 global.tune.options &= ~GTUNE_USE_SPLICE;
481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 else if (!strcmp(args[0], "quiet")) {
483 global.mode |= MODE_QUIET;
484 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200485 else if (!strcmp(args[0], "tune.maxpollevents")) {
486 if (global.tune.maxpollevents != 0) {
487 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200488 err_code |= ERR_ALERT;
489 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 err_code |= ERR_ALERT | ERR_FATAL;
494 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 }
496 global.tune.maxpollevents = atol(args[1]);
497 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100498 else if (!strcmp(args[0], "tune.maxaccept")) {
499 if (global.tune.maxaccept != 0) {
500 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200501 err_code |= ERR_ALERT;
502 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100503 }
504 if (*(args[1]) == 0) {
505 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 }
509 global.tune.maxaccept = atol(args[1]);
510 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200511 else if (!strcmp(args[0], "tune.chksize")) {
512 if (*(args[1]) == 0) {
513 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
514 err_code |= ERR_ALERT | ERR_FATAL;
515 goto out;
516 }
517 global.tune.chksize = atol(args[1]);
518 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200519 else if (!strcmp(args[0], "tune.bufsize")) {
520 if (*(args[1]) == 0) {
521 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
522 err_code |= ERR_ALERT | ERR_FATAL;
523 goto out;
524 }
525 global.tune.bufsize = atol(args[1]);
526 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
527 global.tune.maxrewrite = global.tune.bufsize / 2;
528 }
529 else if (!strcmp(args[0], "tune.maxrewrite")) {
530 if (*(args[1]) == 0) {
531 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
532 err_code |= ERR_ALERT | ERR_FATAL;
533 goto out;
534 }
535 global.tune.maxrewrite = atol(args[1]);
536 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
537 global.tune.maxrewrite = global.tune.bufsize / 2;
538 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100539 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
540 if (global.tune.client_rcvbuf != 0) {
541 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT;
543 goto out;
544 }
545 if (*(args[1]) == 0) {
546 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
547 err_code |= ERR_ALERT | ERR_FATAL;
548 goto out;
549 }
550 global.tune.client_rcvbuf = atol(args[1]);
551 }
552 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
553 if (global.tune.server_rcvbuf != 0) {
554 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
555 err_code |= ERR_ALERT;
556 goto out;
557 }
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.server_rcvbuf = atol(args[1]);
564 }
565 else if (!strcmp(args[0], "tune.sndbuf.client")) {
566 if (global.tune.client_sndbuf != 0) {
567 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT;
569 goto out;
570 }
571 if (*(args[1]) == 0) {
572 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT | ERR_FATAL;
574 goto out;
575 }
576 global.tune.client_sndbuf = atol(args[1]);
577 }
578 else if (!strcmp(args[0], "tune.sndbuf.server")) {
579 if (global.tune.server_sndbuf != 0) {
580 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT;
582 goto out;
583 }
584 if (*(args[1]) == 0) {
585 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588 }
589 global.tune.server_sndbuf = atol(args[1]);
590 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200591 else if (!strcmp(args[0], "tune.pipesize")) {
592 if (*(args[1]) == 0) {
593 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT | ERR_FATAL;
595 goto out;
596 }
597 global.tune.pipesize = atol(args[1]);
598 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200599 else if (!strcmp(args[0], "tune.http.maxhdr")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.max_http_hdr = atol(args[1]);
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 else if (!strcmp(args[0], "uid")) {
608 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 err_code |= ERR_ALERT;
611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 }
613 if (*(args[1]) == 0) {
614 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT | ERR_FATAL;
616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
618 global.uid = atol(args[1]);
619 }
620 else if (!strcmp(args[0], "gid")) {
621 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200622 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200623 err_code |= ERR_ALERT;
624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 }
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 }
631 global.gid = atol(args[1]);
632 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 /* user/group name handling */
634 else if (!strcmp(args[0], "user")) {
635 struct passwd *ha_user;
636 if (global.uid != 0) {
637 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_user = getpwnam(args[1]);
643 if (ha_user != NULL) {
644 global.uid = (int)ha_user->pw_uid;
645 }
646 else {
647 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 else if (!strcmp(args[0], "group")) {
652 struct group *ha_group;
653 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200654 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200657 }
658 errno = 0;
659 ha_group = getgrnam(args[1]);
660 if (ha_group != NULL) {
661 global.gid = (int)ha_group->gr_gid;
662 }
663 else {
664 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200666 }
667 }
668 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 else if (!strcmp(args[0], "nbproc")) {
670 if (global.nbproc != 0) {
671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT;
673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
675 if (*(args[1]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 }
680 global.nbproc = atol(args[1]);
681 }
682 else if (!strcmp(args[0], "maxconn")) {
683 if (global.maxconn != 0) {
684 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200685 err_code |= ERR_ALERT;
686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 }
688 if (*(args[1]) == 0) {
689 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT | ERR_FATAL;
691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 global.maxconn = atol(args[1]);
694#ifdef SYSTEM_MAXCONN
695 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
696 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
697 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 }
700#endif /* SYSTEM_MAXCONN */
701 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200702 else if (!strcmp(args[0], "maxconnrate")) {
703 if (global.cps_lim != 0) {
704 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT;
706 goto out;
707 }
708 if (*(args[1]) == 0) {
709 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 global.cps_lim = atol(args[1]);
714 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100715 else if (!strcmp(args[0], "maxpipes")) {
716 if (global.maxpipes != 0) {
717 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200718 err_code |= ERR_ALERT;
719 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100720 }
721 if (*(args[1]) == 0) {
722 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100725 }
726 global.maxpipes = atol(args[1]);
727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 else if (!strcmp(args[0], "ulimit-n")) {
729 if (global.rlimit_nofile != 0) {
730 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200731 err_code |= ERR_ALERT;
732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 }
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739 global.rlimit_nofile = atol(args[1]);
740 }
741 else if (!strcmp(args[0], "chroot")) {
742 if (global.chroot != NULL) {
743 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200744 err_code |= ERR_ALERT;
745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 }
747 if (*(args[1]) == 0) {
748 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 }
752 global.chroot = strdup(args[1]);
753 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200754 else if (!strcmp(args[0], "description")) {
755 int i, len=0;
756 char *d;
757
758 if (!*args[1]) {
759 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
760 file, linenum, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764
765 for(i=1; *args[i]; i++)
766 len += strlen(args[i])+1;
767
768 if (global.desc)
769 free(global.desc);
770
771 global.desc = d = (char *)calloc(1, len);
772
773 d += sprintf(d, "%s", args[1]);
774 for(i=2; *args[i]; i++)
775 d += sprintf(d, " %s", args[i]);
776 }
777 else if (!strcmp(args[0], "node")) {
778 int i;
779 char c;
780
781 for (i=0; args[1][i]; i++) {
782 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100783 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
784 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200785 break;
786 }
787
788 if (!i || args[1][i]) {
789 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
790 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
791 file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795
796 if (global.node)
797 free(global.node);
798
799 global.node = strdup(args[1]);
800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 else if (!strcmp(args[0], "pidfile")) {
802 if (global.pidfile != NULL) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200804 err_code |= ERR_ALERT;
805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 }
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 }
812 global.pidfile = strdup(args[1]);
813 }
Emeric Bruned760922010-10-22 17:59:25 +0200814 else if (!strcmp(args[0], "unix-bind")) {
815 int cur_arg = 1;
816 while (*(args[cur_arg])) {
817 if (!strcmp(args[cur_arg], "prefix")) {
818 if (global.unix_bind.prefix != NULL) {
819 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
820 err_code |= ERR_ALERT;
821 cur_arg += 2;
822 continue;
823 }
824
825 if (*(args[cur_arg+1]) == 0) {
826 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.unix_bind.prefix = strdup(args[cur_arg+1]);
831 cur_arg += 2;
832 continue;
833 }
834
835 if (!strcmp(args[cur_arg], "mode")) {
836
837 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "uid")) {
843
844 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
845 cur_arg += 2;
846 continue;
847 }
848
849 if (!strcmp(args[cur_arg], "gid")) {
850
851 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
852 cur_arg += 2;
853 continue;
854 }
855
856 if (!strcmp(args[cur_arg], "user")) {
857 struct passwd *user;
858
859 user = getpwnam(args[cur_arg + 1]);
860 if (!user) {
861 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
862 file, linenum, args[0], args[cur_arg + 1 ]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866
867 global.unix_bind.ux.uid = user->pw_uid;
868 cur_arg += 2;
869 continue;
870 }
871
872 if (!strcmp(args[cur_arg], "group")) {
873 struct group *group;
874
875 group = getgrnam(args[cur_arg + 1]);
876 if (!group) {
877 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
878 file, linenum, args[0], args[cur_arg + 1 ]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882
883 global.unix_bind.ux.gid = group->gr_gid;
884 cur_arg += 2;
885 continue;
886 }
887
Willy Tarreaub48f9582011-09-05 01:17:06 +0200888 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200889 file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 }
William Lallemand0f99e342011-10-12 17:50:54 +0200894 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
895 /* delete previous herited or defined syslog servers */
896 struct logsrv *back;
897 struct logsrv *tmp;
898
899 if (*(args[1]) != 0) {
900 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
906 LIST_DEL(&tmp->list);
907 free(tmp);
908 }
909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200911 struct logsrv *logsrv;
912
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 if (*(args[1]) == 0 || *(args[2]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
William Lallemand0f99e342011-10-12 17:50:54 +0200918
919 logsrv = calloc(1, sizeof(struct logsrv));
920
921 logsrv->facility = get_log_facility(args[2]);
922 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200925 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927
William Lallemand0f99e342011-10-12 17:50:54 +0200928 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200930 logsrv->level = get_log_level(args[3]);
931 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200934 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 }
937
William Lallemand0f99e342011-10-12 17:50:54 +0200938 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200939 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200940 logsrv->minlvl = get_log_level(args[4]);
941 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200942 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200944 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 }
946 }
947
Robert Tsai81ae1952007-12-05 10:47:29 +0100948 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100949 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100950 if (!sk) {
951 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100952 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100953 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200954 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100955 goto out;
956 }
William Lallemand0f99e342011-10-12 17:50:54 +0200957 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100958 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100959 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100960 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
962 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200963 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100964 goto out;
965 }
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->addr = *sk;
967 if (!get_host_port(&logsrv->addr))
968 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970
William Lallemand0f99e342011-10-12 17:50:54 +0200971 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200972 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100973 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
974 char *name;
975 int len;
976
977 if (global.log_send_hostname != NULL) {
978 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT;
980 goto out;
981 }
982
983 if (*(args[1]))
984 name = args[1];
985 else
986 name = hostname;
987
988 len = strlen(name);
989
990 /* We'll add a space after the name to respect the log format */
991 free(global.log_send_hostname);
992 global.log_send_hostname = malloc(len + 2);
993 snprintf(global.log_send_hostname, len + 2, "%s ", name);
994 }
Kevinm48936af2010-12-22 16:08:21 +0000995 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
996 if (*(args[1]) == 0) {
997 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 free(global.log_tag);
1002 global.log_tag = strdup(args[1]);
1003 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001004 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1005 if (global.spread_checks != 0) {
1006 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_ALERT;
1008 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001009 }
1010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001014 }
1015 global.spread_checks = atol(args[1]);
1016 if (global.spread_checks < 0 || global.spread_checks > 50) {
1017 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001022 struct cfg_kw_list *kwl;
1023 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001024 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001025
1026 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1027 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1028 if (kwl->kw[index].section != CFG_GLOBAL)
1029 continue;
1030 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1031 /* prepare error message just in case */
1032 snprintf(trash, sizeof(trash),
1033 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001034 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1035 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001036 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001038 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001039 else if (rc > 0) {
1040 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_WARN;
1042 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001043 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001045 }
1046 }
1047 }
1048
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001052
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 out:
1054 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055}
1056
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001057void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001059 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 defproxy.mode = PR_MODE_TCP;
1061 defproxy.state = PR_STNEW;
1062 defproxy.maxconn = cfg_maxpconn;
1063 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001064
1065 defproxy.defsrv.inter = DEF_CHKINTR;
1066 defproxy.defsrv.fastinter = 0;
1067 defproxy.defsrv.downinter = 0;
1068 defproxy.defsrv.rise = DEF_RISETIME;
1069 defproxy.defsrv.fall = DEF_FALLTIME;
1070 defproxy.defsrv.check_port = 0;
1071 defproxy.defsrv.maxqueue = 0;
1072 defproxy.defsrv.minconn = 0;
1073 defproxy.defsrv.maxconn = 0;
1074 defproxy.defsrv.slowstart = 0;
1075 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1076 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1077 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078}
1079
Willy Tarreauade5ec42010-01-28 19:33:49 +01001080
1081static int create_cond_regex_rule(const char *file, int line,
1082 struct proxy *px, int dir, int action, int flags,
1083 const char *cmd, const char *reg, const char *repl,
1084 const char **cond_start)
1085{
1086 regex_t *preg = NULL;
1087 const char *err;
1088 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001089 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001090
1091 if (px == &defproxy) {
1092 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto err;
1095 }
1096
1097 if (*reg == 0) {
1098 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto err;
1101 }
1102
1103 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1104 err_code |= ERR_WARN;
1105
Willy Tarreau5321c422010-01-28 20:35:13 +01001106 if (cond_start &&
1107 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1108 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1109 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1110 file, line, cmd);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto err;
1113 }
1114 }
1115 else if (cond_start && **cond_start) {
1116 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1117 file, line, cmd, *cond_start);
1118 err_code |= ERR_ALERT | ERR_FATAL;
1119 goto err;
1120 }
1121
1122 if (dir == ACL_DIR_REQ)
1123 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001124 else
1125 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001126
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127 preg = calloc(1, sizeof(regex_t));
1128 if (!preg) {
1129 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1130 err_code = ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1135 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1136 err_code = ERR_ALERT | ERR_FATAL;
1137 goto err;
1138 }
1139
1140 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001141 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001142 if (repl && err) {
1143 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1144 file, line, cmd, *err);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto err;
1147 }
1148
1149 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1150 err_code |= ERR_WARN;
1151
1152 return err_code;
1153 err:
1154 free(preg);
1155 return err_code;
1156}
1157
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001159 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001160 * Returns the error code, 0 if OK, or any combination of :
1161 * - ERR_ABORT: must abort ASAP
1162 * - ERR_FATAL: we can continue parsing but not start the service
1163 * - ERR_WARN: a warning has been emitted
1164 * - ERR_ALERT: an alert has been emitted
1165 * Only the two first ones can stop processing, the two others are just
1166 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001168int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1169{
1170 static struct peers *curpeers = NULL;
1171 struct peer *newpeer = NULL;
1172 const char *err;
1173 int err_code = 0;
1174
1175 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1176
1177 err = invalid_char(args[1]);
1178 if (err) {
1179 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1180 file, linenum, *err, args[0], args[1]);
1181 err_code |= ERR_ALERT | ERR_FATAL;
1182 }
1183
1184 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1185 /*
1186 * If there are two proxies with the same name only following
1187 * combinations are allowed:
1188 */
1189 if (strcmp(curpeers->id, args[1]) == 0) {
1190 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1191 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1192 err_code |= ERR_WARN;
1193 }
1194 }
1195
1196 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1198 err_code |= ERR_ALERT | ERR_ABORT;
1199 goto out;
1200 }
1201
1202 curpeers->next = peers;
1203 peers = curpeers;
1204 curpeers->conf.file = file;
1205 curpeers->conf.line = linenum;
1206 curpeers->last_change = now.tv_sec;
1207 curpeers->id = strdup(args[1]);
1208 }
1209 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1210 char *rport, *raddr;
1211 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001212 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001213
1214 if (!*args[2]) {
1215 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1216 file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220
1221 err = invalid_char(args[1]);
1222 if (err) {
1223 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1224 file, linenum, *err, args[1]);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228
1229 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1230 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1231 err_code |= ERR_ALERT | ERR_ABORT;
1232 goto out;
1233 }
1234
1235 /* the peers are linked backwards first */
1236 curpeers->count++;
1237 newpeer->next = curpeers->remote;
1238 curpeers->remote = newpeer;
1239 newpeer->peers = curpeers;
1240 newpeer->conf.file = file;
1241 newpeer->conf.line = linenum;
1242
1243 newpeer->last_change = now.tv_sec;
1244 newpeer->id = strdup(args[1]);
1245
1246 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001247 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001248 if (rport) {
1249 *rport++ = 0;
1250 realport = atol(rport);
1251 }
1252 if (!realport) {
1253 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257
Willy Tarreaufab5a432011-03-04 15:31:53 +01001258 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001259 free(raddr);
1260 if (!sk) {
1261 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
1264 }
1265 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001266 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001267
1268 if (strcmp(newpeer->id, localpeer) == 0) {
1269 /* Current is local peer, it define a frontend */
1270 newpeer->local = 1;
1271
1272 if (!curpeers->peers_fe) {
1273 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1275 err_code |= ERR_ALERT | ERR_ABORT;
1276 goto out;
1277 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001278
Willy Tarreau237250c2011-07-29 01:49:03 +02001279 init_new_proxy(curpeers->peers_fe);
1280 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001281
1282 curpeers->peers_fe->last_change = now.tv_sec;
1283 curpeers->peers_fe->id = strdup(args[1]);
1284 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001285 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001286 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1287 curpeers->peers_fe->timeout.connect = 5000;
1288 curpeers->peers_fe->accept = peer_accept;
1289 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001290 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001291 err_code |= ERR_FATAL;
1292 goto out;
1293 }
1294 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1295 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1296 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1297 curpeers->peers_fe->listen->accept = session_accept;
1298 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1299 curpeers->peers_fe->listen->handler = process_session;
1300 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001301 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1302 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001303 }
1304 }
1305 } /* neither "peer" nor "peers" */
1306 else if (*args[0] != 0) {
1307 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
1310 }
1311
1312out:
1313 return err_code;
1314}
1315
1316
Willy Tarreau3842f002009-06-14 11:39:52 +02001317int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
1319 static struct proxy *curproxy = NULL;
1320 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001321 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001322 int rc;
1323 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001324 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001325 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001326 struct logsrv *tmplogsrv;
1327 struct logformat_node *tmplf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001328
Willy Tarreau977b8e42006-12-29 14:19:17 +01001329 if (!strcmp(args[0], "listen"))
1330 rc = PR_CAP_LISTEN;
1331 else if (!strcmp(args[0], "frontend"))
1332 rc = PR_CAP_FE | PR_CAP_RS;
1333 else if (!strcmp(args[0], "backend"))
1334 rc = PR_CAP_BE | PR_CAP_RS;
1335 else if (!strcmp(args[0], "ruleset"))
1336 rc = PR_CAP_RS;
1337 else
1338 rc = PR_CAP_NONE;
1339
1340 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341 if (!*args[1]) {
1342 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1343 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1344 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001345 err_code |= ERR_ALERT | ERR_ABORT;
1346 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001348
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001349 err = invalid_char(args[1]);
1350 if (err) {
1351 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1352 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001353 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001354 }
1355
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001356 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1357 /*
1358 * If there are two proxies with the same name only following
1359 * combinations are allowed:
1360 *
1361 * listen backend frontend ruleset
1362 * listen - - - -
1363 * backend - - OK -
1364 * frontend - OK - -
1365 * ruleset - - - -
1366 */
1367
1368 if (!strcmp(curproxy->id, args[1]) &&
1369 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1370 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001371 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1372 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1373 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001374 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001375 }
1376 }
1377
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001380 err_code |= ERR_ALERT | ERR_ABORT;
1381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001383
Willy Tarreau97cb7802010-01-03 20:23:58 +01001384 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 curproxy->next = proxy;
1386 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001387 curproxy->conf.file = file;
1388 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001389 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001391 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001392
1393 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001394 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001395 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001396 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001397 err_code |= ERR_FATAL;
1398 goto out;
1399 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001400 new = curproxy->listen;
1401 while (new != last) {
1402 new->conf.file = file;
1403 new->conf.line = linenum;
1404 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001405 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001406 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 }
1408
1409 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001410 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001411 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001412
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001415 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001416 curproxy->no_options = defproxy.no_options;
1417 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001418 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001419 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001420 curproxy->except_net = defproxy.except_net;
1421 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001422 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001423 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001424
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001425 if (defproxy.fwdfor_hdr_len) {
1426 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1427 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1428 }
1429
Willy Tarreaub86db342009-11-30 11:50:16 +01001430 if (defproxy.orgto_hdr_len) {
1431 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1432 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1433 }
1434
Mark Lamourinec2247f02012-01-04 13:02:01 -05001435 if (defproxy.server_id_hdr_len) {
1436 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1437 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1438 }
1439
Willy Tarreau977b8e42006-12-29 14:19:17 +01001440 if (curproxy->cap & PR_CAP_FE) {
1441 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001442 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001443 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001444
1445 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001446 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1447 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001448
1449 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1450 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452 if (curproxy->cap & PR_CAP_BE) {
1453 curproxy->fullconn = defproxy.fullconn;
1454 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001456 if (defproxy.check_req) {
1457 curproxy->check_req = calloc(1, defproxy.check_len);
1458 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1459 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001462 if (defproxy.expect_str) {
1463 curproxy->expect_str = strdup(defproxy.expect_str);
1464 if (defproxy.expect_regex) {
1465 /* note: this regex is known to be valid */
1466 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1467 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1468 }
1469 }
1470
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471 if (defproxy.cookie_name)
1472 curproxy->cookie_name = strdup(defproxy.cookie_name);
1473 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001474 if (defproxy.cookie_domain)
1475 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001476
Willy Tarreau31936852010-10-06 16:59:56 +02001477 if (defproxy.cookie_maxidle)
1478 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1479
1480 if (defproxy.cookie_maxlife)
1481 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1482
Emeric Brun647caf12009-06-30 17:57:00 +02001483 if (defproxy.rdp_cookie_name)
1484 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1485 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1486
Willy Tarreau01732802007-11-01 22:48:15 +01001487 if (defproxy.url_param_name)
1488 curproxy->url_param_name = strdup(defproxy.url_param_name);
1489 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001490
Benoitaffb4812009-03-25 13:02:10 +01001491 if (defproxy.hh_name)
1492 curproxy->hh_name = strdup(defproxy.hh_name);
1493 curproxy->hh_len = defproxy.hh_len;
1494 curproxy->hh_match_domain = defproxy.hh_match_domain;
1495
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001496 if (defproxy.iface_name)
1497 curproxy->iface_name = strdup(defproxy.iface_name);
1498 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001501 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001502 if (defproxy.capture_name)
1503 curproxy->capture_name = strdup(defproxy.capture_name);
1504 curproxy->capture_namelen = defproxy.capture_namelen;
1505 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507
Willy Tarreau977b8e42006-12-29 14:19:17 +01001508 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001509 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001510 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001511 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001512 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001513 curproxy->uri_auth = defproxy.uri_auth;
1514 curproxy->mon_net = defproxy.mon_net;
1515 curproxy->mon_mask = defproxy.mon_mask;
1516 if (defproxy.monitor_uri)
1517 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1518 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001519 if (defproxy.defbe.name)
1520 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001521 }
1522
1523 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001524 curproxy->timeout.connect = defproxy.timeout.connect;
1525 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001526 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001527 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001528 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001529 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001530 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001531 curproxy->source_addr = defproxy.source_addr;
1532 }
1533
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001535
1536 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001537 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001538 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001539 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001540 LIST_INIT(&node->list);
1541 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1542 }
1543
William Lallemand723b73a2012-02-08 16:37:49 +01001544 /* copy default log_format to curproxy */
1545 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1546 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1547 memcpy(node, tmplf, sizeof(struct logformat_node));
1548 LIST_INIT(&node->list);
1549 LIST_ADDQ(&curproxy->logformat, &node->list);
1550 }
1551
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001553 curproxy->conf.used_listener_id = EB_ROOT;
1554 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001555
Willy Tarreau93893792009-07-23 13:19:11 +02001556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 }
1558 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1559 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001560 /* FIXME-20070101: we should do this too at the end of the
1561 * config parsing to free all default values.
1562 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001563 free(defproxy.check_req);
1564 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001565 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001566 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001567 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001568 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001569 free(defproxy.capture_name);
1570 free(defproxy.monitor_uri);
1571 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001572 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001573 free(defproxy.fwdfor_hdr_name);
1574 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001575 free(defproxy.orgto_hdr_name);
1576 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001577 free(defproxy.server_id_hdr_name);
1578 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001579 free(defproxy.expect_str);
1580 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001581
Willy Tarreaua534fea2008-08-03 12:19:50 +02001582 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001583 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 /* we cannot free uri_auth because it might already be used */
1586 init_default_instance();
1587 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001588 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 }
1591 else if (curproxy == NULL) {
1592 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 }
1596
Willy Tarreau977b8e42006-12-29 14:19:17 +01001597
1598 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001600 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001601 int cur_arg;
1602
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 if (curproxy == &defproxy) {
1604 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001605 err_code |= ERR_ALERT | ERR_FATAL;
1606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001608 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001609 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610
Emeric Bruned760922010-10-22 17:59:25 +02001611 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001612 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001614 err_code |= ERR_ALERT | ERR_FATAL;
1615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001617
1618 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001619
1620 /* NOTE: the following line might create several listeners if there
1621 * are comma-separated IPs or port ranges. So all further processing
1622 * will have to be applied to all listeners created after last_listen.
1623 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001624 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001625 err_code |= ERR_ALERT | ERR_FATAL;
1626 goto out;
1627 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001628
Willy Tarreau90a570f2009-10-04 20:54:54 +02001629 new_listen = curproxy->listen;
1630 while (new_listen != last_listen) {
1631 new_listen->conf.file = file;
1632 new_listen->conf.line = linenum;
1633 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001634 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001635 }
1636
Emeric Bruned760922010-10-22 17:59:25 +02001637 /* Set default global rights and owner for unix bind */
1638 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1639 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1640 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001641 cur_arg = 2;
1642 while (*(args[cur_arg])) {
1643 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1644#ifdef SO_BINDTODEVICE
1645 struct listener *l;
1646
Emeric Bruned760922010-10-22 17:59:25 +02001647 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1648 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1649 file, linenum, args[0], args[cur_arg]);
1650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
1652 }
1653
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001654 if (!*args[cur_arg + 1]) {
1655 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1656 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001659 }
1660
1661 for (l = curproxy->listen; l != last_listen; l = l->next)
1662 l->interface = strdup(args[cur_arg + 1]);
1663
1664 global.last_checks |= LSTCHK_NETADM;
1665
1666 cur_arg += 2;
1667 continue;
1668#else
1669 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1670 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_ALERT | ERR_FATAL;
1672 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001673#endif
1674 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001675 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1676#ifdef TCP_MAXSEG
1677 struct listener *l;
1678 int mss;
1679
Emeric Bruned760922010-10-22 17:59:25 +02001680 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1681 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1682 file, linenum, args[0], args[cur_arg]);
1683 err_code |= ERR_ALERT | ERR_FATAL;
1684 goto out;
1685 }
1686
Willy Tarreaube1b9182009-06-14 18:48:19 +02001687 if (!*args[cur_arg + 1]) {
1688 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1689 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001692 }
1693
Willy Tarreau48a7e722010-12-24 15:26:39 +01001694 mss = atoi(args[cur_arg + 1]);
1695 if (!mss || abs(mss) > 65535) {
1696 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001697 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001698 err_code |= ERR_ALERT | ERR_FATAL;
1699 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001700 }
1701
1702 for (l = curproxy->listen; l != last_listen; l = l->next)
1703 l->maxseg = mss;
1704
1705 cur_arg += 2;
1706 continue;
1707#else
1708 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1709 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001712#endif
1713 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001714
1715 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1716#ifdef TCP_DEFER_ACCEPT
1717 struct listener *l;
1718
1719 for (l = curproxy->listen; l != last_listen; l = l->next)
1720 l->options |= LI_O_DEF_ACCEPT;
1721
1722 cur_arg ++;
1723 continue;
1724#else
1725 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1726 file, linenum, args[0], args[cur_arg]);
1727 err_code |= ERR_ALERT | ERR_FATAL;
1728 goto out;
1729#endif
1730 }
1731
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001732 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001733#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734 struct listener *l;
1735
Emeric Bruned760922010-10-22 17:59:25 +02001736 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1737 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1738 file, linenum, args[0], args[cur_arg]);
1739 err_code |= ERR_ALERT | ERR_FATAL;
1740 goto out;
1741 }
1742
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001743 for (l = curproxy->listen; l != last_listen; l = l->next)
1744 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001745
1746 cur_arg ++;
1747 continue;
1748#else
1749 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1750 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001751 err_code |= ERR_ALERT | ERR_FATAL;
1752 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001753#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001754 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001755
Willy Tarreau8a956912010-10-15 14:27:08 +02001756 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1757 struct listener *l;
1758
1759 for (l = curproxy->listen; l != last_listen; l = l->next)
1760 l->options |= LI_O_ACC_PROXY;
1761
1762 cur_arg ++;
1763 continue;
1764 }
1765
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001766 if (!strcmp(args[cur_arg], "name")) {
1767 struct listener *l;
1768
1769 for (l = curproxy->listen; l != last_listen; l = l->next)
1770 l->name = strdup(args[cur_arg + 1]);
1771
1772 cur_arg += 2;
1773 continue;
1774 }
1775
1776 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001777 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001778 struct listener *l;
1779
1780 if (curproxy->listen->next != last_listen) {
1781 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1782 file, linenum, args[cur_arg]);
1783 err_code |= ERR_ALERT | ERR_FATAL;
1784 goto out;
1785 }
1786
1787 if (!*args[cur_arg + 1]) {
1788 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1789 file, linenum, args[cur_arg]);
1790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
1792 }
1793
1794 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001795 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001796
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001797 if (curproxy->listen->luid <= 0) {
1798 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001799 file, linenum);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
1802 }
1803
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001804 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1805 if (node) {
1806 l = container_of(node, struct listener, conf.id);
1807 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1808 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
1812 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1813
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001814 cur_arg += 2;
1815 continue;
1816 }
1817
Emeric Bruned760922010-10-22 17:59:25 +02001818 if (!strcmp(args[cur_arg], "mode")) {
1819
1820 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1821 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1822 file, linenum, args[0], args[cur_arg]);
1823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
1825 }
1826
1827 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1828
1829 cur_arg += 2;
1830 continue;
1831 }
1832
1833 if (!strcmp(args[cur_arg], "uid")) {
1834
1835 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1836 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1837 file, linenum, args[0], args[cur_arg]);
1838 err_code |= ERR_ALERT | ERR_FATAL;
1839 goto out;
1840 }
1841
1842 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1843 cur_arg += 2;
1844 continue;
1845 }
1846
1847 if (!strcmp(args[cur_arg], "gid")) {
1848
1849 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1850 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1851 file, linenum, args[0], args[cur_arg]);
1852 err_code |= ERR_ALERT | ERR_FATAL;
1853 goto out;
1854 }
1855
1856 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1857 cur_arg += 2;
1858 continue;
1859 }
1860
1861 if (!strcmp(args[cur_arg], "user")) {
1862 struct passwd *user;
1863
1864 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1865 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1866 file, linenum, args[0], args[cur_arg]);
1867 err_code |= ERR_ALERT | ERR_FATAL;
1868 goto out;
1869 }
1870 user = getpwnam(args[cur_arg + 1]);
1871 if (!user) {
1872 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1873 file, linenum, args[0], args[cur_arg + 1 ]);
1874 err_code |= ERR_ALERT | ERR_FATAL;
1875 goto out;
1876 }
1877
1878 curproxy->listen->perm.ux.uid = user->pw_uid;
1879 cur_arg += 2;
1880 continue;
1881 }
1882
1883 if (!strcmp(args[cur_arg], "group")) {
1884 struct group *group;
1885
1886 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1887 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1888 file, linenum, args[0], args[cur_arg]);
1889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
1891 }
1892 group = getgrnam(args[cur_arg + 1]);
1893 if (!group) {
1894 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1895 file, linenum, args[0], args[cur_arg + 1 ]);
1896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
1898 }
1899
1900 curproxy->listen->perm.ux.gid = group->gr_gid;
1901 cur_arg += 2;
1902 continue;
1903 }
1904
Willy Tarreaub48f9582011-09-05 01:17:06 +02001905 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 +01001906 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001907 err_code |= ERR_ALERT | ERR_FATAL;
1908 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001909 }
Willy Tarreau93893792009-07-23 13:19:11 +02001910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001911 }
1912 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1913 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1914 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1915 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001916 err_code |= ERR_ALERT | ERR_FATAL;
1917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001918 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001919 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001920 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921
Willy Tarreaubaaee002006-06-26 02:48:02 +02001922 /* flush useless bits */
1923 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001925 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001926 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001927 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001928 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001929
Willy Tarreau1c47f852006-07-09 08:22:27 +02001930 if (!*args[1]) {
1931 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1932 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001935 }
1936
Willy Tarreaua534fea2008-08-03 12:19:50 +02001937 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001938 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001939 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001940 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001941 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1942
Willy Tarreau93893792009-07-23 13:19:11 +02001943 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1946 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1947 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1948 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1949 else {
1950 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_ALERT | ERR_FATAL;
1952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001953 }
1954 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001955 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001956 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001957
1958 if (curproxy == &defproxy) {
1959 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1960 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001961 err_code |= ERR_ALERT | ERR_FATAL;
1962 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001963 }
1964
1965 if (!*args[1]) {
1966 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1967 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001968 err_code |= ERR_ALERT | ERR_FATAL;
1969 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001970 }
1971
1972 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001973 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001974
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001975 if (curproxy->uuid <= 0) {
1976 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001977 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001978 err_code |= ERR_ALERT | ERR_FATAL;
1979 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001980 }
1981
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001982 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1983 if (node) {
1984 struct proxy *target = container_of(node, struct proxy, conf.id);
1985 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1986 file, linenum, proxy_type_str(curproxy), curproxy->id,
1987 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
1990 }
1991 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001992 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001993 else if (!strcmp(args[0], "description")) {
1994 int i, len=0;
1995 char *d;
1996
Cyril Bonté99ed3272010-01-24 23:29:44 +01001997 if (curproxy == &defproxy) {
1998 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1999 file, linenum, args[0]);
2000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
2002 }
2003
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002004 if (!*args[1]) {
2005 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2006 file, linenum, args[0]);
2007 return -1;
2008 }
2009
2010 for(i=1; *args[i]; i++)
2011 len += strlen(args[i])+1;
2012
2013 d = (char *)calloc(1, len);
2014 curproxy->desc = d;
2015
2016 d += sprintf(d, "%s", args[1]);
2017 for(i=2; *args[i]; i++)
2018 d += sprintf(d, " %s", args[i]);
2019
2020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2022 curproxy->state = PR_STSTOPPED;
2023 }
2024 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2025 curproxy->state = PR_STNEW;
2026 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002027 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2028 int cur_arg = 1;
2029 unsigned int set = 0;
2030
2031 while (*args[cur_arg]) {
2032 int u;
2033 if (strcmp(args[cur_arg], "all") == 0) {
2034 set = 0;
2035 break;
2036 }
2037 else if (strcmp(args[cur_arg], "odd") == 0) {
2038 set |= 0x55555555;
2039 }
2040 else if (strcmp(args[cur_arg], "even") == 0) {
2041 set |= 0xAAAAAAAA;
2042 }
2043 else {
2044 u = str2uic(args[cur_arg]);
2045 if (u < 1 || u > 32) {
2046 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002050 }
2051 if (u > global.nbproc) {
2052 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2053 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002054 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002055 }
2056 set |= 1 << (u - 1);
2057 }
2058 cur_arg++;
2059 }
2060 curproxy->bind_proc = set;
2061 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002062 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002063 if (curproxy == &defproxy) {
2064 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002065 err_code |= ERR_ALERT | ERR_FATAL;
2066 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002067 }
2068
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002069 err = invalid_char(args[1]);
2070 if (err) {
2071 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2072 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002073 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002074 }
2075
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002076 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2077 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2078 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002081 }
2082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2084 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002087 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002088
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 if (*(args[1]) == 0) {
2090 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2091 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002095
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002096 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002097 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002098 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002099 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002100 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 curproxy->cookie_name = strdup(args[1]);
2102 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002103
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 cur_arg = 2;
2105 while (*(args[cur_arg])) {
2106 if (!strcmp(args[cur_arg], "rewrite")) {
2107 curproxy->options |= PR_O_COOK_RW;
2108 }
2109 else if (!strcmp(args[cur_arg], "indirect")) {
2110 curproxy->options |= PR_O_COOK_IND;
2111 }
2112 else if (!strcmp(args[cur_arg], "insert")) {
2113 curproxy->options |= PR_O_COOK_INS;
2114 }
2115 else if (!strcmp(args[cur_arg], "nocache")) {
2116 curproxy->options |= PR_O_COOK_NOC;
2117 }
2118 else if (!strcmp(args[cur_arg], "postonly")) {
2119 curproxy->options |= PR_O_COOK_POST;
2120 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002121 else if (!strcmp(args[cur_arg], "preserve")) {
2122 curproxy->options2 |= PR_O2_COOK_PSV;
2123 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124 else if (!strcmp(args[cur_arg], "prefix")) {
2125 curproxy->options |= PR_O_COOK_PFX;
2126 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002127 else if (!strcmp(args[cur_arg], "domain")) {
2128 if (!*args[cur_arg + 1]) {
2129 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2130 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002133 }
2134
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002135 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002136 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002137 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2138 " dots nor does not start with a dot."
2139 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002140 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002141 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002142 }
2143
2144 err = invalid_domainchar(args[cur_arg + 1]);
2145 if (err) {
2146 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2147 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002148 err_code |= ERR_ALERT | ERR_FATAL;
2149 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002150 }
2151
Willy Tarreau68a897b2009-12-03 23:28:34 +01002152 if (!curproxy->cookie_domain) {
2153 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2154 } else {
2155 /* one domain was already specified, add another one by
2156 * building the string which will be returned along with
2157 * the cookie.
2158 */
2159 char *new_ptr;
2160 int new_len = strlen(curproxy->cookie_domain) +
2161 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2162 new_ptr = malloc(new_len);
2163 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2164 free(curproxy->cookie_domain);
2165 curproxy->cookie_domain = new_ptr;
2166 }
Willy Tarreau31936852010-10-06 16:59:56 +02002167 cur_arg++;
2168 }
2169 else if (!strcmp(args[cur_arg], "maxidle")) {
2170 unsigned int maxidle;
2171 const char *res;
2172
2173 if (!*args[cur_arg + 1]) {
2174 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2175 file, linenum, args[cur_arg]);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179
2180 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2181 if (res) {
2182 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2183 file, linenum, *res, args[cur_arg]);
2184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
2186 }
2187 curproxy->cookie_maxidle = maxidle;
2188 cur_arg++;
2189 }
2190 else if (!strcmp(args[cur_arg], "maxlife")) {
2191 unsigned int maxlife;
2192 const char *res;
2193
2194 if (!*args[cur_arg + 1]) {
2195 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2196 file, linenum, args[cur_arg]);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200
2201 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2202 if (res) {
2203 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2204 file, linenum, *res, args[cur_arg]);
2205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
2207 }
2208 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002209 cur_arg++;
2210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002212 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 +02002213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }
2217 cur_arg++;
2218 }
2219 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2220 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2221 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002222 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002223 }
2224
2225 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2226 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2227 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002228 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002230
2231 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2232 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2233 file, linenum);
2234 err_code |= ERR_ALERT | ERR_FATAL;
2235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002237 else if (!strcmp(args[0], "persist")) { /* persist */
2238 if (*(args[1]) == 0) {
2239 Alert("parsing [%s:%d] : missing persist method.\n",
2240 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002243 }
2244
2245 if (!strncmp(args[1], "rdp-cookie", 10)) {
2246 curproxy->options2 |= PR_O2_RDPC_PRST;
2247
Emeric Brunb982a3d2010-01-04 15:45:53 +01002248 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002249 const char *beg, *end;
2250
2251 beg = args[1] + 11;
2252 end = strchr(beg, ')');
2253
2254 if (!end || end == beg) {
2255 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2256 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002257 err_code |= ERR_ALERT | ERR_FATAL;
2258 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002259 }
2260
2261 free(curproxy->rdp_cookie_name);
2262 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2263 curproxy->rdp_cookie_len = end-beg;
2264 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002265 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002266 free(curproxy->rdp_cookie_name);
2267 curproxy->rdp_cookie_name = strdup("msts");
2268 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2269 }
2270 else { /* syntax */
2271 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2272 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002275 }
2276 }
2277 else {
2278 Alert("parsing [%s:%d] : unknown persist method.\n",
2279 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002282 }
2283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002285 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002287 if (curproxy == &defproxy) {
2288 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
2291 }
2292
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002295
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002297 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
2302 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002303 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002304 curproxy->appsession_name = strdup(args[1]);
2305 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2306 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002307 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2308 if (err) {
2309 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2310 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002313 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002314 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002315
Willy Tarreau51041c72007-09-09 21:56:53 +02002316 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2317 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_ALERT | ERR_ABORT;
2319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002321
2322 cur_arg = 6;
2323 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002324 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2325 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002326 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002327 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002328 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002329 } else if (!strcmp(args[cur_arg], "prefix")) {
2330 curproxy->options2 |= PR_O2_AS_PFX;
2331 } else if (!strcmp(args[cur_arg], "mode")) {
2332 if (!*args[cur_arg + 1]) {
2333 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2334 file, linenum, args[0], args[cur_arg]);
2335 err_code |= ERR_ALERT | ERR_FATAL;
2336 goto out;
2337 }
2338
2339 cur_arg++;
2340 if (!strcmp(args[cur_arg], "query-string")) {
2341 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2342 curproxy->options2 |= PR_O2_AS_M_QS;
2343 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2344 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2345 curproxy->options2 |= PR_O2_AS_M_PP;
2346 } else {
2347 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002352 cur_arg++;
2353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 } /* Url App Session */
2355 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002356 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002358
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002360 if (curproxy == &defproxy) {
2361 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 if (*(args[4]) == 0) {
2367 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2368 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002372 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 curproxy->capture_name = strdup(args[2]);
2374 curproxy->capture_namelen = strlen(curproxy->capture_name);
2375 curproxy->capture_len = atol(args[4]);
2376 if (curproxy->capture_len >= CAPTURE_LEN) {
2377 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2378 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 curproxy->capture_len = CAPTURE_LEN - 1;
2381 }
2382 curproxy->to_log |= LW_COOKIE;
2383 }
2384 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2385 struct cap_hdr *hdr;
2386
2387 if (curproxy == &defproxy) {
2388 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 +02002389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 }
2392
2393 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2394 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2395 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
2399
2400 hdr = calloc(sizeof(struct cap_hdr), 1);
2401 hdr->next = curproxy->req_cap;
2402 hdr->name = strdup(args[3]);
2403 hdr->namelen = strlen(args[3]);
2404 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002405 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 hdr->index = curproxy->nb_req_cap++;
2407 curproxy->req_cap = hdr;
2408 curproxy->to_log |= LW_REQHDR;
2409 }
2410 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2411 struct cap_hdr *hdr;
2412
2413 if (curproxy == &defproxy) {
2414 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 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 }
2418
2419 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2420 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2421 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002422 err_code |= ERR_ALERT | ERR_FATAL;
2423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 }
2425 hdr = calloc(sizeof(struct cap_hdr), 1);
2426 hdr->next = curproxy->rsp_cap;
2427 hdr->name = strdup(args[3]);
2428 hdr->namelen = strlen(args[3]);
2429 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002430 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 hdr->index = curproxy->nb_rsp_cap++;
2432 curproxy->rsp_cap = hdr;
2433 curproxy->to_log |= LW_RSPHDR;
2434 }
2435 else {
2436 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2437 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 }
2441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002443 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002445
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 if (*(args[1]) == 0) {
2447 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2448 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002449 err_code |= ERR_ALERT | ERR_FATAL;
2450 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }
2452 curproxy->conn_retries = atol(args[1]);
2453 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002454 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002455 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002456
2457 if (curproxy == &defproxy) {
2458 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462
Willy Tarreauff011f22011-01-06 17:51:27 +01002463 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 +01002464 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2465 file, linenum, args[0]);
2466 err_code |= ERR_WARN;
2467 }
2468
Willy Tarreauff011f22011-01-06 17:51:27 +01002469 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002470
Willy Tarreauff011f22011-01-06 17:51:27 +01002471 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002472 err_code |= ERR_ALERT | ERR_ABORT;
2473 goto out;
2474 }
2475
Willy Tarreauff011f22011-01-06 17:51:27 +01002476 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2477 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002478 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002479 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2480 /* set the header name and length into the proxy structure */
2481 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2482 err_code |= ERR_WARN;
2483
2484 if (!*args[1]) {
2485 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2486 file, linenum, args[0]);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490
2491 /* set the desired header name */
2492 free(curproxy->server_id_hdr_name);
2493 curproxy->server_id_hdr_name = strdup(args[1]);
2494 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2495 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002496 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002497 if (curproxy == &defproxy) {
2498 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002499 err_code |= ERR_ALERT | ERR_FATAL;
2500 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002501 }
2502
Willy Tarreauef6494c2010-01-28 17:12:36 +01002503 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002504 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2505 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002508 }
2509
Willy Tarreauef6494c2010-01-28 17:12:36 +01002510 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002511 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2512 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002513 err_code |= ERR_ALERT | ERR_FATAL;
2514 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002515 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002516
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002517 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002518 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002519 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002520 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002521 struct redirect_rule *rule;
2522 int cur_arg;
2523 int type = REDIRECT_TYPE_NONE;
2524 int code = 302;
2525 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002526 char *cookie = NULL;
2527 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002528 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002529
Cyril Bonté99ed3272010-01-24 23:29:44 +01002530 if (curproxy == &defproxy) {
2531 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
2534 }
2535
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002536 cur_arg = 1;
2537 while (*(args[cur_arg])) {
2538 if (!strcmp(args[cur_arg], "location")) {
2539 if (!*args[cur_arg + 1]) {
2540 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2541 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002544 }
2545
2546 type = REDIRECT_TYPE_LOCATION;
2547 cur_arg++;
2548 destination = args[cur_arg];
2549 }
2550 else if (!strcmp(args[cur_arg], "prefix")) {
2551 if (!*args[cur_arg + 1]) {
2552 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2553 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002556 }
2557
2558 type = REDIRECT_TYPE_PREFIX;
2559 cur_arg++;
2560 destination = args[cur_arg];
2561 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002562 else if (!strcmp(args[cur_arg], "set-cookie")) {
2563 if (!*args[cur_arg + 1]) {
2564 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2565 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002568 }
2569
2570 cur_arg++;
2571 cookie = args[cur_arg];
2572 cookie_set = 1;
2573 }
2574 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2575 if (!*args[cur_arg + 1]) {
2576 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2577 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_ALERT | ERR_FATAL;
2579 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002580 }
2581
2582 cur_arg++;
2583 cookie = args[cur_arg];
2584 cookie_set = 0;
2585 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 else if (!strcmp(args[cur_arg],"code")) {
2587 if (!*args[cur_arg + 1]) {
2588 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2589 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002592 }
2593 cur_arg++;
2594 code = atol(args[cur_arg]);
2595 if (code < 301 || code > 303) {
2596 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2597 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 }
2601 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002602 else if (!strcmp(args[cur_arg],"drop-query")) {
2603 flags |= REDIRECT_FLAG_DROP_QS;
2604 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002605 else if (!strcmp(args[cur_arg],"append-slash")) {
2606 flags |= REDIRECT_FLAG_APPEND_SLASH;
2607 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002608 else if (strcmp(args[cur_arg], "if") == 0 ||
2609 strcmp(args[cur_arg], "unless") == 0) {
2610 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2611 if (!cond) {
2612 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2613 file, linenum, args[0]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002617 break;
2618 }
2619 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002620 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 +02002621 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002624 }
2625 cur_arg++;
2626 }
2627
2628 if (type == REDIRECT_TYPE_NONE) {
2629 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002633 }
2634
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002635 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2636 rule->cond = cond;
2637 rule->rdr_str = strdup(destination);
2638 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002639 if (cookie) {
2640 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002641 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002642 */
2643 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002644 if (cookie_set) {
2645 rule->cookie_str = malloc(rule->cookie_len + 10);
2646 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2647 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2648 rule->cookie_len += 9;
2649 } else {
2650 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002651 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002652 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2653 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002654 }
2655 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002656 rule->type = type;
2657 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002658 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002659 LIST_INIT(&rule->list);
2660 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002661 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2662 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002663 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002664 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002665 struct switching_rule *rule;
2666
Willy Tarreaub099aca2008-10-12 17:26:37 +02002667 if (curproxy == &defproxy) {
2668 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002671 }
2672
Willy Tarreau55ea7572007-06-17 19:56:27 +02002673 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002674 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002675
2676 if (*(args[1]) == 0) {
2677 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002680 }
2681
Willy Tarreauef6494c2010-01-28 17:12:36 +01002682 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002683 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2684 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002687 }
2688
Willy Tarreauef6494c2010-01-28 17:12:36 +01002689 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002690 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002691 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002694 }
2695
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002696 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002697
Willy Tarreau55ea7572007-06-17 19:56:27 +02002698 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2699 rule->cond = cond;
2700 rule->be.name = strdup(args[1]);
2701 LIST_INIT(&rule->list);
2702 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2703 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002704 else if ((!strcmp(args[0], "force-persist")) ||
2705 (!strcmp(args[0], "ignore-persist"))) {
2706 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002707
2708 if (curproxy == &defproxy) {
2709 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713
2714 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2715 err_code |= ERR_WARN;
2716
Willy Tarreauef6494c2010-01-28 17:12:36 +01002717 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002718 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2719 file, linenum, args[0]);
2720 err_code |= ERR_ALERT | ERR_FATAL;
2721 goto out;
2722 }
2723
Willy Tarreauef6494c2010-01-28 17:12:36 +01002724 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002725 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2726 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
2729 }
2730
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002731 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002732
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002733 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002734 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002735 if (!strcmp(args[0], "force-persist")) {
2736 rule->type = PERSIST_TYPE_FORCE;
2737 } else {
2738 rule->type = PERSIST_TYPE_IGNORE;
2739 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002740 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002741 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002742 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002743 else if (!strcmp(args[0], "stick-table")) {
2744 int myidx = 1;
2745
Emeric Brun32da3c42010-09-23 18:39:19 +02002746 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002747 curproxy->table.type = (unsigned int)-1;
2748 while (*args[myidx]) {
2749 const char *err;
2750
2751 if (strcmp(args[myidx], "size") == 0) {
2752 myidx++;
2753 if (!*(args[myidx])) {
2754 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2755 file, linenum, args[myidx-1]);
2756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
2758 }
2759 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2760 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2761 file, linenum, *err, args[myidx-1]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002765 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002766 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002767 else if (strcmp(args[myidx], "peers") == 0) {
2768 myidx++;
2769 if (!*(args[myidx])) {
2770 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2771 file, linenum, args[myidx-1]);
2772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
2774 }
2775 curproxy->table.peers.name = strdup(args[myidx++]);
2776 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002777 else if (strcmp(args[myidx], "expire") == 0) {
2778 myidx++;
2779 if (!*(args[myidx])) {
2780 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2781 file, linenum, args[myidx-1]);
2782 err_code |= ERR_ALERT | ERR_FATAL;
2783 goto out;
2784 }
2785 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2786 if (err) {
2787 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2788 file, linenum, *err, args[myidx-1]);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
2792 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002793 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002794 }
2795 else if (strcmp(args[myidx], "nopurge") == 0) {
2796 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002797 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002798 }
2799 else if (strcmp(args[myidx], "type") == 0) {
2800 myidx++;
2801 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2802 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2803 file, linenum, args[myidx]);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002807 /* myidx already points to next arg */
2808 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002809 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002810 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002811 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002812
2813 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002814 nw = args[myidx];
2815 while (*nw) {
2816 /* the "store" keyword supports a comma-separated list */
2817 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002818 sa = NULL; /* store arg */
2819 while (*nw && *nw != ',') {
2820 if (*nw == '(') {
2821 *nw = 0;
2822 sa = ++nw;
2823 while (*nw != ')') {
2824 if (!*nw) {
2825 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2826 file, linenum, args[0], cw);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
2830 nw++;
2831 }
2832 *nw = '\0';
2833 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002834 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002835 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002836 if (*nw)
2837 *nw++ = '\0';
2838 type = stktable_get_data_type(cw);
2839 if (type < 0) {
2840 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2841 file, linenum, args[0], cw);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
Willy Tarreauac782882010-06-20 10:41:54 +02002845
2846 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2847 switch (err) {
2848 case PE_NONE: break;
2849 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002850 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2851 file, linenum, args[0], cw);
2852 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002853 break;
2854
2855 case PE_ARG_MISSING:
2856 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2857 file, linenum, args[0], cw);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860
2861 case PE_ARG_NOT_USED:
2862 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2863 file, linenum, args[0], cw);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866
2867 default:
2868 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2869 file, linenum, args[0], cw);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002872 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002873 }
2874 myidx++;
2875 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002876 else {
2877 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2878 file, linenum, args[myidx]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002881 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002882 }
2883
2884 if (!curproxy->table.size) {
2885 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2886 file, linenum);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890
2891 if (curproxy->table.type == (unsigned int)-1) {
2892 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2893 file, linenum);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
2897 }
2898 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002899 struct sticking_rule *rule;
2900 struct pattern_expr *expr;
2901 int myidx = 0;
2902 const char *name = NULL;
2903 int flags;
2904
2905 if (curproxy == &defproxy) {
2906 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
2909 }
2910
2911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2912 err_code |= ERR_WARN;
2913 goto out;
2914 }
2915
2916 myidx++;
2917 if ((strcmp(args[myidx], "store") == 0) ||
2918 (strcmp(args[myidx], "store-request") == 0)) {
2919 myidx++;
2920 flags = STK_IS_STORE;
2921 }
2922 else if (strcmp(args[myidx], "store-response") == 0) {
2923 myidx++;
2924 flags = STK_IS_STORE | STK_ON_RSP;
2925 }
2926 else if (strcmp(args[myidx], "match") == 0) {
2927 myidx++;
2928 flags = STK_IS_MATCH;
2929 }
2930 else if (strcmp(args[myidx], "on") == 0) {
2931 myidx++;
2932 flags = STK_IS_MATCH | STK_IS_STORE;
2933 }
2934 else {
2935 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
2939
2940 if (*(args[myidx]) == 0) {
2941 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
Emeric Brun485479d2010-09-23 18:02:19 +02002946 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002947 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002948 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
2953 if (flags & STK_ON_RSP) {
2954 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2955 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2956 file, linenum, args[0], expr->fetch->kw);
2957 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002958 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002959 goto out;
2960 }
2961 } else {
2962 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2963 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2964 file, linenum, args[0], expr->fetch->kw);
2965 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002966 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002967 goto out;
2968 }
2969 }
2970
2971 if (strcmp(args[myidx], "table") == 0) {
2972 myidx++;
2973 name = args[myidx++];
2974 }
2975
Willy Tarreauef6494c2010-01-28 17:12:36 +01002976 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2977 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002978 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2979 file, linenum, args[0]);
2980 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002981 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002982 goto out;
2983 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002984 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002985 else if (*(args[myidx])) {
2986 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2987 file, linenum, args[0], args[myidx]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002989 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002990 goto out;
2991 }
Emeric Brun97679e72010-09-23 17:56:44 +02002992 if (flags & STK_ON_RSP)
2993 err_code |= warnif_cond_requires_req(cond, file, linenum);
2994 else
2995 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002996
Emeric Brunb982a3d2010-01-04 15:45:53 +01002997 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2998 rule->cond = cond;
2999 rule->expr = expr;
3000 rule->flags = flags;
3001 rule->table.name = name ? strdup(name) : NULL;
3002 LIST_INIT(&rule->list);
3003 if (flags & STK_ON_RSP)
3004 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3005 else
3006 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003009 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003010 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003011
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3013 curproxy->uri_auth = NULL; /* we must detach from the default config */
3014
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003015 if (!*args[1]) {
3016 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003017 } else if (!strcmp(args[1], "admin")) {
3018 struct stats_admin_rule *rule;
3019
3020 if (curproxy == &defproxy) {
3021 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3027 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3028 err_code |= ERR_ALERT | ERR_ABORT;
3029 goto out;
3030 }
3031
3032 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3033 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3034 file, linenum, args[0], args[1]);
3035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
3037 }
3038 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3039 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3040 file, linenum, args[0], args[1]);
3041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
3043 }
3044
3045 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3046
3047 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3048 rule->cond = cond;
3049 LIST_INIT(&rule->list);
3050 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 } else if (!strcmp(args[1], "uri")) {
3052 if (*(args[2]) == 0) {
3053 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3057 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003058 err_code |= ERR_ALERT | ERR_ABORT;
3059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 }
3061 } else if (!strcmp(args[1], "realm")) {
3062 if (*(args[2]) == 0) {
3063 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3067 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_ABORT;
3069 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003071 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003072 unsigned interval;
3073
3074 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3075 if (err) {
3076 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3077 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003080 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3081 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_ALERT | ERR_ABORT;
3083 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003084 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003085 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003086 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003087
3088 if (curproxy == &defproxy) {
3089 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
3092 }
3093
3094 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3095 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3096 err_code |= ERR_ALERT | ERR_ABORT;
3097 goto out;
3098 }
3099
Willy Tarreauff011f22011-01-06 17:51:27 +01003100 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3101 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003102 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3103 file, linenum, args[0]);
3104 err_code |= ERR_WARN;
3105 }
3106
Willy Tarreauff011f22011-01-06 17:51:27 +01003107 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003108
Willy Tarreauff011f22011-01-06 17:51:27 +01003109 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003110 err_code |= ERR_ALERT | ERR_ABORT;
3111 goto out;
3112 }
3113
Willy Tarreauff011f22011-01-06 17:51:27 +01003114 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3115 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003116
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 } else if (!strcmp(args[1], "auth")) {
3118 if (*(args[2]) == 0) {
3119 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_ABORT;
3125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
3127 } else if (!strcmp(args[1], "scope")) {
3128 if (*(args[2]) == 0) {
3129 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3133 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003134 err_code |= ERR_ALERT | ERR_ABORT;
3135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 }
3137 } else if (!strcmp(args[1], "enable")) {
3138 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3139 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_ALERT | ERR_ABORT;
3141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003143 } else if (!strcmp(args[1], "hide-version")) {
3144 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3145 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003146 err_code |= ERR_ALERT | ERR_ABORT;
3147 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003148 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003149 } else if (!strcmp(args[1], "show-legends")) {
3150 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3151 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3152 err_code |= ERR_ALERT | ERR_ABORT;
3153 goto out;
3154 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003155 } else if (!strcmp(args[1], "show-node")) {
3156
3157 if (*args[2]) {
3158 int i;
3159 char c;
3160
3161 for (i=0; args[2][i]; i++) {
3162 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003163 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3164 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003165 break;
3166 }
3167
3168 if (!i || args[2][i]) {
3169 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3170 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3171 file, linenum, args[0], args[1]);
3172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
3174 }
3175 }
3176
3177 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3178 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3179 err_code |= ERR_ALERT | ERR_ABORT;
3180 goto out;
3181 }
3182 } else if (!strcmp(args[1], "show-desc")) {
3183 char *desc = NULL;
3184
3185 if (*args[2]) {
3186 int i, len=0;
3187 char *d;
3188
3189 for(i=2; *args[i]; i++)
3190 len += strlen(args[i])+1;
3191
3192 desc = d = (char *)calloc(1, len);
3193
3194 d += sprintf(d, "%s", args[2]);
3195 for(i=3; *args[i]; i++)
3196 d += sprintf(d, " %s", args[i]);
3197 }
3198
3199 if (!*args[2] && !global.desc)
3200 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3201 file, linenum, args[1]);
3202 else {
3203 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3204 free(desc);
3205 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3206 err_code |= ERR_ALERT | ERR_ABORT;
3207 goto out;
3208 }
3209 free(desc);
3210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003212stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003213 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 +01003214 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 }
3218 }
3219 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003220 int optnum;
3221
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003222 if (*(args[1]) == '\0') {
3223 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3224 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003228
3229 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3230 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003231 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3232 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3233 file, linenum, cfg_opts[optnum].name);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
Willy Tarreau93893792009-07-23 13:19:11 +02003237 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3238 err_code |= ERR_WARN;
3239 goto out;
3240 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003241
Willy Tarreau3842f002009-06-14 11:39:52 +02003242 curproxy->no_options &= ~cfg_opts[optnum].val;
3243 curproxy->options &= ~cfg_opts[optnum].val;
3244
3245 switch (kwm) {
3246 case KWM_STD:
3247 curproxy->options |= cfg_opts[optnum].val;
3248 break;
3249 case KWM_NO:
3250 curproxy->no_options |= cfg_opts[optnum].val;
3251 break;
3252 case KWM_DEF: /* already cleared */
3253 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003254 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003255
Willy Tarreau93893792009-07-23 13:19:11 +02003256 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003257 }
3258 }
3259
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003260 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3261 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003262 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3263 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3264 file, linenum, cfg_opts2[optnum].name);
3265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
3267 }
Willy Tarreau93893792009-07-23 13:19:11 +02003268 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3269 err_code |= ERR_WARN;
3270 goto out;
3271 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003272
Willy Tarreau3842f002009-06-14 11:39:52 +02003273 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3274 curproxy->options2 &= ~cfg_opts2[optnum].val;
3275
3276 switch (kwm) {
3277 case KWM_STD:
3278 curproxy->options2 |= cfg_opts2[optnum].val;
3279 break;
3280 case KWM_NO:
3281 curproxy->no_options2 |= cfg_opts2[optnum].val;
3282 break;
3283 case KWM_DEF: /* already cleared */
3284 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003285 }
Willy Tarreau93893792009-07-23 13:19:11 +02003286 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003287 }
3288 }
3289
Willy Tarreau3842f002009-06-14 11:39:52 +02003290 if (kwm != KWM_STD) {
3291 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003292 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003295 }
3296
Emeric Brun3a058f32009-06-30 18:26:00 +02003297 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003298 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003300 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
William Lallemand723b73a2012-02-08 16:37:49 +01003302 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003303 if (*(args[2]) != '\0') {
3304 if (!strcmp(args[2], "clf")) {
3305 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003306 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003307 } else {
3308 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003311 }
3312 }
William Lallemand723b73a2012-02-08 16:37:49 +01003313 parse_logformat_string(logformat, curproxy);
Emeric Brun3a058f32009-06-30 18:26:00 +02003314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003315 else if (!strcmp(args[1], "tcplog"))
3316 /* generate a detailed TCP log */
3317 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 else if (!strcmp(args[1], "tcpka")) {
3319 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003320 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003322
3323 if (curproxy->cap & PR_CAP_FE)
3324 curproxy->options |= PR_O_TCP_CLI_KA;
3325 if (curproxy->cap & PR_CAP_BE)
3326 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003329 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_WARN;
3331
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003333 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003334 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003335 curproxy->options2 &= ~PR_O2_CHK_ANY;
3336 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 if (!*args[2]) { /* no argument */
3338 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3339 curproxy->check_len = strlen(DEF_CHECK_REQ);
3340 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003341 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 curproxy->check_req = (char *)malloc(reqlen);
3343 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003344 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003346 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 if (*args[4])
3348 reqlen += strlen(args[4]);
3349 else
3350 reqlen += strlen("HTTP/1.0");
3351
3352 curproxy->check_req = (char *)malloc(reqlen);
3353 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003354 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003356 }
3357 else if (!strcmp(args[1], "ssl-hello-chk")) {
3358 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003359 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003361
Willy Tarreaua534fea2008-08-03 12:19:50 +02003362 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003363 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003364 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003365 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 }
Willy Tarreau23677902007-05-08 23:50:35 +02003367 else if (!strcmp(args[1], "smtpchk")) {
3368 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003369 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003370 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003371 curproxy->options2 &= ~PR_O2_CHK_ANY;
3372 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003373
3374 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3375 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3376 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3377 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3378 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3379 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3380 curproxy->check_req = (char *)malloc(reqlen);
3381 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3382 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3383 } else {
3384 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3385 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3386 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3387 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3388 }
3389 }
3390 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003391 else if (!strcmp(args[1], "pgsql-check")) {
3392 /* use PostgreSQL request to check servers' health */
3393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3394 err_code |= ERR_WARN;
3395
3396 free(curproxy->check_req);
3397 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003398 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003399 curproxy->options2 |= PR_O2_PGSQL_CHK;
3400
3401 if (*(args[2])) {
3402 int cur_arg = 2;
3403
3404 while (*(args[cur_arg])) {
3405 if (strcmp(args[cur_arg], "user") == 0) {
3406 char * packet;
3407 uint32_t packet_len;
3408 uint32_t pv;
3409
3410 /* suboption header - needs additional argument for it */
3411 if (*(args[cur_arg+1]) == 0) {
3412 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3413 file, linenum, args[0], args[1], args[cur_arg]);
3414 err_code |= ERR_ALERT | ERR_FATAL;
3415 goto out;
3416 }
3417
3418 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3419 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3420 pv = htonl(0x30000); /* protocol version 3.0 */
3421
3422 packet = (char*) calloc(1, packet_len);
3423
3424 memcpy(packet + 4, &pv, 4);
3425
3426 /* copy "user" */
3427 memcpy(packet + 8, "user", 4);
3428
3429 /* copy username */
3430 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3431
3432 free(curproxy->check_req);
3433 curproxy->check_req = packet;
3434 curproxy->check_len = packet_len;
3435
3436 packet_len = htonl(packet_len);
3437 memcpy(packet, &packet_len, 4);
3438 cur_arg += 2;
3439 } else {
3440 /* unknown suboption - catchall */
3441 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3442 file, linenum, args[0], args[1]);
3443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
3445 }
3446 } /* end while loop */
3447 }
3448 }
3449
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003450 else if (!strcmp(args[1], "redis-check")) {
3451 /* use REDIS PING request to check servers' health */
3452 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3453 err_code |= ERR_WARN;
3454
3455 free(curproxy->check_req);
3456 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003457 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003458 curproxy->options2 |= PR_O2_REDIS_CHK;
3459
3460 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3461 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3462 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3463 }
3464
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003465 else if (!strcmp(args[1], "mysql-check")) {
3466 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003467 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3468 err_code |= ERR_WARN;
3469
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003470 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003471 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003472 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003473 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003474
3475 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3476 * const char mysql40_client_auth_pkt[] = {
3477 * "\x0e\x00\x00" // packet length
3478 * "\x01" // packet number
3479 * "\x00\x00" // client capabilities
3480 * "\x00\x00\x01" // max packet
3481 * "haproxy\x00" // username (null terminated string)
3482 * "\x00" // filler (always 0x00)
3483 * "\x01\x00\x00" // packet length
3484 * "\x00" // packet number
3485 * "\x01" // COM_QUIT command
3486 * };
3487 */
3488
3489 if (*(args[2])) {
3490 int cur_arg = 2;
3491
3492 while (*(args[cur_arg])) {
3493 if (strcmp(args[cur_arg], "user") == 0) {
3494 char *mysqluser;
3495 int packetlen, reqlen, userlen;
3496
3497 /* suboption header - needs additional argument for it */
3498 if (*(args[cur_arg+1]) == 0) {
3499 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3500 file, linenum, args[0], args[1], args[cur_arg]);
3501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
3503 }
3504 mysqluser = args[cur_arg + 1];
3505 userlen = strlen(mysqluser);
3506 packetlen = userlen + 7;
3507 reqlen = packetlen + 9;
3508
3509 free(curproxy->check_req);
3510 curproxy->check_req = (char *)calloc(1, reqlen);
3511 curproxy->check_len = reqlen;
3512
3513 snprintf(curproxy->check_req, 4, "%c%c%c",
3514 ((unsigned char) packetlen & 0xff),
3515 ((unsigned char) (packetlen >> 8) & 0xff),
3516 ((unsigned char) (packetlen >> 16) & 0xff));
3517
3518 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003519 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003520 curproxy->check_req[8] = 1;
3521 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3522 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3523 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3524 cur_arg += 2;
3525 } else {
3526 /* unknown suboption - catchall */
3527 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3528 file, linenum, args[0], args[1]);
3529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
3531 }
3532 } /* end while loop */
3533 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003534 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003535 else if (!strcmp(args[1], "ldap-check")) {
3536 /* use LDAP request to check servers' health */
3537 free(curproxy->check_req);
3538 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003539 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003540 curproxy->options2 |= PR_O2_LDAP_CHK;
3541
3542 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3543 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3544 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3545 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003546 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003547 int cur_arg;
3548
3549 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3550 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003551 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003552
Willy Tarreau87cf5142011-08-19 22:57:24 +02003553 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003554
3555 free(curproxy->fwdfor_hdr_name);
3556 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3557 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3558
3559 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3560 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_net, &curproxy->except_mask)) {
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;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003569 }
3570 /* flush useless bits */
3571 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003572 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;
Ross Westaf72a1d2008-08-03 10:51:45 +02003580 }
3581 free(curproxy->fwdfor_hdr_name);
3582 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3583 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3584 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003585 } else if (!strcmp(args[cur_arg], "if-none")) {
3586 curproxy->options &= ~PR_O_FF_ALWAYS;
3587 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003588 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003589 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003590 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003591 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_ALERT | ERR_FATAL;
3593 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003594 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003595 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003596 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003597 else if (!strcmp(args[1], "originalto")) {
3598 int cur_arg;
3599
3600 /* insert x-original-to field, but not for the IP address listed as an except.
3601 * set default options (ie: bitfield, header name, etc)
3602 */
3603
3604 curproxy->options |= PR_O_ORGTO;
3605
3606 free(curproxy->orgto_hdr_name);
3607 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3608 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3609
Willy Tarreau87cf5142011-08-19 22:57:24 +02003610 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003611 cur_arg = 2;
3612 while (*(args[cur_arg])) {
3613 if (!strcmp(args[cur_arg], "except")) {
3614 /* suboption except - needs additional argument for it */
3615 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3616 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3617 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003620 }
3621 /* flush useless bits */
3622 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3623 cur_arg += 2;
3624 } else if (!strcmp(args[cur_arg], "header")) {
3625 /* suboption header - needs additional argument for it */
3626 if (*(args[cur_arg+1]) == 0) {
3627 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3628 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003631 }
3632 free(curproxy->orgto_hdr_name);
3633 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3634 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3635 cur_arg += 2;
3636 } else {
3637 /* unknown suboption - catchall */
3638 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3639 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003642 }
3643 } /* end while loop */
3644 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003645 else {
3646 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 }
Willy Tarreau93893792009-07-23 13:19:11 +02003650 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003652 else if (!strcmp(args[0], "default_backend")) {
3653 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003654 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003655
3656 if (*(args[1]) == 0) {
3657 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003660 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003661 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003662 curproxy->defbe.name = strdup(args[1]);
3663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003665 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003667
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003668 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 /* enable reconnections to dispatch */
3672 curproxy->options |= PR_O_REDISP;
3673 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003674 else if (!strcmp(args[0], "http-check")) {
3675 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003677
3678 if (strcmp(args[1], "disable-on-404") == 0) {
3679 /* enable a graceful server shutdown on an HTTP 404 response */
3680 curproxy->options |= PR_O_DISABLE404;
3681 }
Willy Tarreauef781042010-01-27 11:53:01 +01003682 else if (strcmp(args[1], "send-state") == 0) {
3683 /* enable emission of the apparent state of a server in HTTP checks */
3684 curproxy->options2 |= PR_O2_CHK_SNDST;
3685 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003686 else if (strcmp(args[1], "expect") == 0) {
3687 const char *ptr_arg;
3688 int cur_arg;
3689
3690 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3691 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
3694 }
3695
3696 cur_arg = 2;
3697 /* consider exclamation marks, sole or at the beginning of a word */
3698 while (*(ptr_arg = args[cur_arg])) {
3699 while (*ptr_arg == '!') {
3700 curproxy->options2 ^= PR_O2_EXP_INV;
3701 ptr_arg++;
3702 }
3703 if (*ptr_arg)
3704 break;
3705 cur_arg++;
3706 }
3707 /* now ptr_arg points to the beginning of a word past any possible
3708 * exclamation mark, and cur_arg is the argument which holds this word.
3709 */
3710 if (strcmp(ptr_arg, "status") == 0) {
3711 if (!*(args[cur_arg + 1])) {
3712 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3713 file, linenum, args[0], args[1], ptr_arg);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003718 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003719 curproxy->expect_str = strdup(args[cur_arg + 1]);
3720 }
3721 else if (strcmp(ptr_arg, "string") == 0) {
3722 if (!*(args[cur_arg + 1])) {
3723 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3724 file, linenum, args[0], args[1], ptr_arg);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
3728 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003729 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003730 curproxy->expect_str = strdup(args[cur_arg + 1]);
3731 }
3732 else if (strcmp(ptr_arg, "rstatus") == 0) {
3733 if (!*(args[cur_arg + 1])) {
3734 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3735 file, linenum, args[0], args[1], ptr_arg);
3736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
3738 }
3739 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003740 free(curproxy->expect_str);
3741 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3742 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003743 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3744 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3745 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3746 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
3749 }
3750 }
3751 else if (strcmp(ptr_arg, "rstring") == 0) {
3752 if (!*(args[cur_arg + 1])) {
3753 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3754 file, linenum, args[0], args[1], ptr_arg);
3755 err_code |= ERR_ALERT | ERR_FATAL;
3756 goto out;
3757 }
3758 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003759 free(curproxy->expect_str);
3760 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3761 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003762 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3763 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3764 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3765 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
3768 }
3769 }
3770 else {
3771 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3772 file, linenum, args[0], args[1], ptr_arg);
3773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
3775 }
3776 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003777 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003778 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 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003781 }
3782 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003783 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003784 if (curproxy == &defproxy) {
3785 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003788 }
3789
Willy Tarreaub80c2302007-11-30 20:51:32 +01003790 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003792
3793 if (strcmp(args[1], "fail") == 0) {
3794 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003795 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003796 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3797 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003800 }
3801
Willy Tarreauef6494c2010-01-28 17:12:36 +01003802 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003803 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3804 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003807 }
3808 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3809 }
3810 else {
3811 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003814 }
3815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816#ifdef TPROXY
3817 else if (!strcmp(args[0], "transparent")) {
3818 /* enable transparent proxy connections */
3819 curproxy->options |= PR_O_TRANSP;
3820 }
3821#endif
3822 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003823 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003824 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003825
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 if (*(args[1]) == 0) {
3827 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 }
3831 curproxy->maxconn = atol(args[1]);
3832 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003833 else if (!strcmp(args[0], "backlog")) { /* backlog */
3834 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003836
3837 if (*(args[1]) == 0) {
3838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003841 }
3842 curproxy->backlog = atol(args[1]);
3843 }
Willy Tarreau86034312006-12-29 00:10:33 +01003844 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003845 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003847
Willy Tarreau86034312006-12-29 00:10:33 +01003848 if (*(args[1]) == 0) {
3849 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003852 }
3853 curproxy->fullconn = atol(args[1]);
3854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3856 if (*(args[1]) == 0) {
3857 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003861 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3862 if (err) {
3863 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3864 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003867 }
3868 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003869 }
3870 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003871 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 if (curproxy == &defproxy) {
3873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003877 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003879
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 if (strchr(args[1], ':') == NULL) {
3881 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_ALERT | ERR_FATAL;
3883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003885 sk = str2sa(args[1]);
3886 if (!sk) {
3887 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
3890 }
3891 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003892 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
3894 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003895 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003897
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003898 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003899 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3900 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003905 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3906 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3907 err_code |= ERR_WARN;
3908
3909 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3910 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3911 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3912 }
3913 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3914 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3915 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3916 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003917 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3918 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3919 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3920 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003921 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003922 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
3925 }
3926 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003927 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003929 char *rport, *raddr;
3930 short realport = 0;
3931 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003932
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003933 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003938 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003940
3941 if (!*args[2]) {
3942 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3943 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
3945 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003946 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003947
3948 err = invalid_char(args[1]);
3949 if (err) {
3950 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3951 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003954 }
3955
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003956 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003957 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003958
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003959 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3960 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3961 err_code |= ERR_ALERT | ERR_ABORT;
3962 goto out;
3963 }
3964
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003965 /* the servers are linked backwards first */
3966 newsrv->next = curproxy->srv;
3967 curproxy->srv = newsrv;
3968 newsrv->proxy = curproxy;
3969 newsrv->conf.file = file;
3970 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003971
Simon Hormanaf514952011-06-21 14:34:57 +09003972 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003973 LIST_INIT(&newsrv->pendconns);
3974 do_check = 0;
3975 newsrv->state = SRV_RUNNING; /* early server setup */
3976 newsrv->last_change = now.tv_sec;
3977 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003979 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003980 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003981 * - IP: => port=+0, relative
3982 * - IP:N => port=N, absolute
3983 * - IP:+N => port=+N, relative
3984 * - IP:-N => port=-N, relative
3985 */
3986 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003987 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003988 if (rport) {
3989 *rport++ = 0;
3990 realport = atol(rport);
3991 if (!isdigit((unsigned char)*rport))
3992 newsrv->state |= SRV_MAPPORTS;
3993 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003994 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003995
Willy Tarreaufab5a432011-03-04 15:31:53 +01003996 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003997 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003998 if (!sk) {
3999 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
4002 }
4003 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004004 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004005
4006 newsrv->check_port = curproxy->defsrv.check_port;
4007 newsrv->inter = curproxy->defsrv.inter;
4008 newsrv->fastinter = curproxy->defsrv.fastinter;
4009 newsrv->downinter = curproxy->defsrv.downinter;
4010 newsrv->rise = curproxy->defsrv.rise;
4011 newsrv->fall = curproxy->defsrv.fall;
4012 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4013 newsrv->minconn = curproxy->defsrv.minconn;
4014 newsrv->maxconn = curproxy->defsrv.maxconn;
4015 newsrv->slowstart = curproxy->defsrv.slowstart;
4016 newsrv->onerror = curproxy->defsrv.onerror;
4017 newsrv->consecutive_errors_limit
4018 = curproxy->defsrv.consecutive_errors_limit;
4019 newsrv->uweight = newsrv->iweight
4020 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004022 newsrv->curfd = -1; /* no health-check in progress */
4023 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 cur_arg = 3;
4026 } else {
4027 newsrv = &curproxy->defsrv;
4028 cur_arg = 1;
4029 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004030
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004032 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004033 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004034
4035 if (!*args[cur_arg + 1]) {
4036 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4037 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004040 }
4041
4042 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004043 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004044
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004045 if (newsrv->puid <= 0) {
4046 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004047 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004048 err_code |= ERR_ALERT | ERR_FATAL;
4049 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004050 }
4051
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004052 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4053 if (node) {
4054 struct server *target = container_of(node, struct server, conf.id);
4055 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4056 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
4060 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004061 cur_arg += 2;
4062 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004063 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004064 newsrv->cookie = strdup(args[cur_arg + 1]);
4065 newsrv->cklen = strlen(args[cur_arg + 1]);
4066 cur_arg += 2;
4067 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004068 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004069 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4070 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4071 cur_arg += 2;
4072 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004073 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004074 if (!*args[cur_arg + 1]) {
4075 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4076 file, linenum, args[cur_arg]);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080
Willy Tarreaubaaee002006-06-26 02:48:02 +02004081 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004082 if (newsrv->rise <= 0) {
4083 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4084 file, linenum, args[cur_arg]);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
4088
Willy Tarreau96839092010-03-29 10:02:24 +02004089 if (newsrv->health)
4090 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004091 cur_arg += 2;
4092 }
4093 else if (!strcmp(args[cur_arg], "fall")) {
4094 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004095
4096 if (!*args[cur_arg + 1]) {
4097 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4098 file, linenum, args[cur_arg]);
4099 err_code |= ERR_ALERT | ERR_FATAL;
4100 goto out;
4101 }
4102
4103 if (newsrv->fall <= 0) {
4104 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4105 file, linenum, args[cur_arg]);
4106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
4108 }
4109
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 cur_arg += 2;
4111 }
4112 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004113 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4114 if (err) {
4115 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4116 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004119 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004120 if (val <= 0) {
4121 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4122 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004125 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004126 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 cur_arg += 2;
4128 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004129 else if (!strcmp(args[cur_arg], "fastinter")) {
4130 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4131 if (err) {
4132 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4133 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004136 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004137 if (val <= 0) {
4138 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4139 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004142 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004143 newsrv->fastinter = val;
4144 cur_arg += 2;
4145 }
4146 else if (!strcmp(args[cur_arg], "downinter")) {
4147 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4148 if (err) {
4149 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4150 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004153 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004154 if (val <= 0) {
4155 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4156 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004159 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004160 newsrv->downinter = val;
4161 cur_arg += 2;
4162 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004163 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004164 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004165 if (!sk) {
4166 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004171 cur_arg += 2;
4172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173 else if (!strcmp(args[cur_arg], "port")) {
4174 newsrv->check_port = atol(args[cur_arg + 1]);
4175 cur_arg += 2;
4176 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004177 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 newsrv->state |= SRV_BACKUP;
4179 cur_arg ++;
4180 }
Simon Hormanfa461682011-06-25 09:39:49 +09004181 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4182 newsrv->state |= SRV_NON_STICK;
4183 cur_arg ++;
4184 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004185 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4186 newsrv->state |= SRV_SEND_PROXY;
4187 cur_arg ++;
4188 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004189 else if (!strcmp(args[cur_arg], "weight")) {
4190 int w;
4191 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004192 if (w < 0 || w > 256) {
4193 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004198 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 cur_arg += 2;
4200 }
4201 else if (!strcmp(args[cur_arg], "minconn")) {
4202 newsrv->minconn = atol(args[cur_arg + 1]);
4203 cur_arg += 2;
4204 }
4205 else if (!strcmp(args[cur_arg], "maxconn")) {
4206 newsrv->maxconn = atol(args[cur_arg + 1]);
4207 cur_arg += 2;
4208 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004209 else if (!strcmp(args[cur_arg], "maxqueue")) {
4210 newsrv->maxqueue = atol(args[cur_arg + 1]);
4211 cur_arg += 2;
4212 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004213 else if (!strcmp(args[cur_arg], "slowstart")) {
4214 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004215 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004216 if (err) {
4217 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4218 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004221 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004222 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004223 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4224 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004227 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004228 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004229 cur_arg += 2;
4230 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004231 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004232
4233 if (!*args[cur_arg + 1]) {
4234 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4235 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004238 }
4239
4240 newsrv->trackit = strdup(args[cur_arg + 1]);
4241
4242 cur_arg += 2;
4243 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004244 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 global.maxsock++;
4246 do_check = 1;
4247 cur_arg += 1;
4248 }
Willy Tarreau96839092010-03-29 10:02:24 +02004249 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4250 newsrv->state |= SRV_MAINTAIN;
4251 newsrv->state &= ~SRV_RUNNING;
4252 newsrv->health = 0;
4253 cur_arg += 1;
4254 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004255 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004256 if (!strcmp(args[cur_arg + 1], "none"))
4257 newsrv->observe = HANA_OBS_NONE;
4258 else if (!strcmp(args[cur_arg + 1], "layer4"))
4259 newsrv->observe = HANA_OBS_LAYER4;
4260 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4261 if (curproxy->mode != PR_MODE_HTTP) {
4262 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4263 file, linenum, args[cur_arg + 1]);
4264 err_code |= ERR_ALERT;
4265 }
4266 newsrv->observe = HANA_OBS_LAYER7;
4267 }
4268 else {
4269 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004270 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004271 file, linenum, args[cur_arg], args[cur_arg + 1]);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275
4276 cur_arg += 2;
4277 }
4278 else if (!strcmp(args[cur_arg], "on-error")) {
4279 if (!strcmp(args[cur_arg + 1], "fastinter"))
4280 newsrv->onerror = HANA_ONERR_FASTINTER;
4281 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4282 newsrv->onerror = HANA_ONERR_FAILCHK;
4283 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4284 newsrv->onerror = HANA_ONERR_SUDDTH;
4285 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4286 newsrv->onerror = HANA_ONERR_MARKDWN;
4287 else {
4288 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004289 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004290 file, linenum, args[cur_arg], args[cur_arg + 1]);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294
4295 cur_arg += 2;
4296 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004297 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4298 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4299 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4300 else {
4301 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4302 file, linenum, args[cur_arg], args[cur_arg + 1]);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306
4307 cur_arg += 2;
4308 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004309 else if (!strcmp(args[cur_arg], "error-limit")) {
4310 if (!*args[cur_arg + 1]) {
4311 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4312 file, linenum, args[cur_arg]);
4313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
4315 }
4316
4317 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4318
4319 if (newsrv->consecutive_errors_limit <= 0) {
4320 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4321 file, linenum, args[cur_arg]);
4322 err_code |= ERR_ALERT | ERR_FATAL;
4323 goto out;
4324 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004325 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004326 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004327 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004328 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004329 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004330
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004332#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004333 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004334 file, linenum, "source", "usesrc");
4335#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004336 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004338#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004339 err_code |= ERR_ALERT | ERR_FATAL;
4340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004341 }
4342 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004343 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4344 if (!sk) {
4345 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004350
4351 if (port_low != port_high) {
4352 int i;
4353 if (port_low <= 0 || port_low > 65535 ||
4354 port_high <= 0 || port_high > 65535 ||
4355 port_low > port_high) {
4356 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4357 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004360 }
4361 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4362 for (i = 0; i < newsrv->sport_range->size; i++)
4363 newsrv->sport_range->ports[i] = port_low + i;
4364 }
4365
Willy Tarreaubaaee002006-06-26 02:48:02 +02004366 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004367 while (*(args[cur_arg])) {
4368 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004369#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4370#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004371 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4372 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4373 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004376 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004377#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004378 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004379 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004380 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 }
4384 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004385 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 newsrv->state |= SRV_TPROXY_CLI;
4387 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004388 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004389 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004390 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4391 char *name, *end;
4392
4393 name = args[cur_arg+1] + 7;
4394 while (isspace(*name))
4395 name++;
4396
4397 end = name;
4398 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4399 end++;
4400
4401 newsrv->state &= ~SRV_TPROXY_MASK;
4402 newsrv->state |= SRV_TPROXY_DYN;
4403 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4404 newsrv->bind_hdr_len = end - name;
4405 memcpy(newsrv->bind_hdr_name, name, end - name);
4406 newsrv->bind_hdr_name[end-name] = '\0';
4407 newsrv->bind_hdr_occ = -1;
4408
4409 /* now look for an occurrence number */
4410 while (isspace(*end))
4411 end++;
4412 if (*end == ',') {
4413 end++;
4414 name = end;
4415 if (*end == '-')
4416 end++;
4417 while (isdigit(*end))
4418 end++;
4419 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4420 }
4421
4422 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4423 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4424 " occurrences values smaller than %d.\n",
4425 file, linenum, MAX_HDR_HISTORY);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004430 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004431 if (!sk) {
4432 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4433 err_code |= ERR_ALERT | ERR_FATAL;
4434 goto out;
4435 }
4436 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004437 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004438 }
4439 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004440#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004441 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004442#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004443 cur_arg += 2;
4444 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004445#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004446 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004447 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004450#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4451 } /* "usesrc" */
4452
4453 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4454#ifdef SO_BINDTODEVICE
4455 if (!*args[cur_arg + 1]) {
4456 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4457 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004458 err_code |= ERR_ALERT | ERR_FATAL;
4459 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004460 }
4461 if (newsrv->iface_name)
4462 free(newsrv->iface_name);
4463
4464 newsrv->iface_name = strdup(args[cur_arg + 1]);
4465 newsrv->iface_len = strlen(newsrv->iface_name);
4466 global.last_checks |= LSTCHK_NETADM;
4467#else
4468 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4469 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004472#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004473 cur_arg += 2;
4474 continue;
4475 }
4476 /* this keyword in not an option of "source" */
4477 break;
4478 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004480 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004481 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4482 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004486 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004487 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004488 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 +01004489 file, linenum, newsrv->id);
4490 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004491 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 +01004492 file, linenum);
4493
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 }
4497 }
4498
4499 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004500 if (newsrv->trackit) {
4501 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4502 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004505 }
4506
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004507 /* try to get the port from check_addr if check_port not set */
4508 if (!newsrv->check_port)
4509 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004510
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4512 newsrv->check_port = realport; /* by default */
4513 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004514 /* not yet valid, because no port was set on
4515 * the server either. We'll check if we have
4516 * a known port on the first listener.
4517 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004518 struct listener *l = curproxy->listen;
4519 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4520 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004521 }
4522 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4524 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004528
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004529 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004530 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004531 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4532 err_code |= ERR_ALERT | ERR_ABORT;
4533 goto out;
4534 }
4535
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004536 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004537 newsrv->state |= SRV_CHECKED;
4538 }
4539
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004540 if (!defsrv) {
4541 if (newsrv->state & SRV_BACKUP)
4542 curproxy->srv_bck++;
4543 else
4544 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004545
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004546 newsrv->prev_state = newsrv->state;
4547 }
William Lallemand723b73a2012-02-08 16:37:49 +01004548 }
4549 else if (strcmp(args[0], "log-format") == 0) {
4550 if (!*(args[1])) {
4551 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555 parse_logformat_string(args[1], curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004556 }
William Lallemand723b73a2012-02-08 16:37:49 +01004557
William Lallemand0f99e342011-10-12 17:50:54 +02004558 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4559 /* delete previous herited or defined syslog servers */
4560 struct logsrv *back;
4561
4562 if (*(args[1]) != 0) {
4563 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4564 err_code |= ERR_ALERT | ERR_FATAL;
4565 goto out;
4566 }
4567
William Lallemand723b73a2012-02-08 16:37:49 +01004568 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4569 LIST_DEL(&tmplogsrv->list);
4570 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004571 }
4572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004574 struct logsrv *logsrv;
4575
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004577 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004578 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004579 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004580 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004581 LIST_INIT(&node->list);
4582 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 }
4585 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004586
4587 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004588
William Lallemand0f99e342011-10-12 17:50:54 +02004589 logsrv->facility = get_log_facility(args[2]);
4590 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596
William Lallemand0f99e342011-10-12 17:50:54 +02004597 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004599 logsrv->level = get_log_level(args[3]);
4600 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 }
4606 }
4607
William Lallemand0f99e342011-10-12 17:50:54 +02004608 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004609 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004610 logsrv->minlvl = get_log_level(args[4]);
4611 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004612 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
4615
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004616 }
4617 }
4618
Robert Tsai81ae1952007-12-05 10:47:29 +01004619 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004620 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004621 if (!sk) {
4622 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004623 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004624 err_code |= ERR_ALERT | ERR_FATAL;
4625 goto out;
4626 }
William Lallemand0f99e342011-10-12 17:50:54 +02004627 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004628 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004629 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004630 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004631 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
William Lallemand0f99e342011-10-12 17:50:54 +02004635 logsrv->addr = *sk;
4636 if (!get_host_port(&logsrv->addr))
4637 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004638 }
William Lallemand0f99e342011-10-12 17:50:54 +02004639
4640 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 }
4642 else {
4643 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4644 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 }
4648 }
4649 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004650 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004651 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004652
Willy Tarreau977b8e42006-12-29 14:19:17 +01004653 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004655
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004657 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4658 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004662
4663 /* we must first clear any optional default setting */
4664 curproxy->options &= ~PR_O_TPXY_MASK;
4665 free(curproxy->iface_name);
4666 curproxy->iface_name = NULL;
4667 curproxy->iface_len = 0;
4668
Willy Tarreaud5191e72010-02-09 20:50:45 +01004669 sk = str2sa(args[1]);
4670 if (!sk) {
4671 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
4675 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004677
4678 cur_arg = 2;
4679 while (*(args[cur_arg])) {
4680 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004681#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4682#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004683 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4684 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4685 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004688 }
4689#endif
4690 if (!*args[cur_arg + 1]) {
4691 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4692 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004695 }
4696
4697 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004698 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699 curproxy->options |= PR_O_TPXY_CLI;
4700 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004701 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004702 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004703 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4704 char *name, *end;
4705
4706 name = args[cur_arg+1] + 7;
4707 while (isspace(*name))
4708 name++;
4709
4710 end = name;
4711 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4712 end++;
4713
4714 curproxy->options &= ~PR_O_TPXY_MASK;
4715 curproxy->options |= PR_O_TPXY_DYN;
4716 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4717 curproxy->bind_hdr_len = end - name;
4718 memcpy(curproxy->bind_hdr_name, name, end - name);
4719 curproxy->bind_hdr_name[end-name] = '\0';
4720 curproxy->bind_hdr_occ = -1;
4721
4722 /* now look for an occurrence number */
4723 while (isspace(*end))
4724 end++;
4725 if (*end == ',') {
4726 end++;
4727 name = end;
4728 if (*end == '-')
4729 end++;
4730 while (isdigit(*end))
4731 end++;
4732 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4733 }
4734
4735 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4736 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4737 " occurrences values smaller than %d.\n",
4738 file, linenum, MAX_HDR_HISTORY);
4739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
4741 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004742 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004743 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004744 if (!sk) {
4745 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
4748 }
4749 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004750 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004751 }
4752 global.last_checks |= LSTCHK_NETADM;
4753#if !defined(CONFIG_HAP_LINUX_TPROXY)
4754 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004755#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004756#else /* no TPROXY support */
4757 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004758 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004761#endif
4762 cur_arg += 2;
4763 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004764 }
4765
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004766 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4767#ifdef SO_BINDTODEVICE
4768 if (!*args[cur_arg + 1]) {
4769 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4770 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004773 }
4774 if (curproxy->iface_name)
4775 free(curproxy->iface_name);
4776
4777 curproxy->iface_name = strdup(args[cur_arg + 1]);
4778 curproxy->iface_len = strlen(curproxy->iface_name);
4779 global.last_checks |= LSTCHK_NETADM;
4780#else
4781 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4782 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004785#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004786 cur_arg += 2;
4787 continue;
4788 }
4789 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4790 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004795 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4796 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4797 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004801 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4804 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808
4809 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4810 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004811 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004812 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 }
4815 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004816 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4817 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004818 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004819 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004821 }
4822 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4824 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004825 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004826 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 }
4829 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004830 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4831 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004832 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004833 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
4836 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004837 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4838 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004839 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004840 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004841 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004843 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004844 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4845 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004846 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004847 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004848 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004849 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004850 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004851 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4852 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004853 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004855 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004856 }
4857 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004858 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4859 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004860 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004861 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004862 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004865 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4867 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004871
4872 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4873 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004874 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004875 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
4878 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004879 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4880 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004881 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004882 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 }
4885 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004886 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4887 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004888 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004889 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 }
4892 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004893 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4894 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004895 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004896 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
4899 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004900 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4901 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004902 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004903 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004905 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004906 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4908 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004909 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004910 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004911 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004914 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004915
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 if (curproxy == &defproxy) {
4917 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004921 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 if (*(args[1]) == 0) {
4925 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004929
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004930 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4931 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4932 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4933 file, linenum, args[0]);
4934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
4936 }
4937 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4938 }
4939 else if (*args[2]) {
4940 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4941 file, linenum, args[0], args[2]);
4942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
4944 }
4945
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004946 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004947 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004948 wl->s = strdup(args[1]);
4949 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004950 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
4952 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004954 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004956 err_code |= ERR_ALERT | ERR_FATAL;
4957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004959
Willy Tarreauade5ec42010-01-28 19:33:49 +01004960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4961 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004962 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4968 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004974 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4975 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004976 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004977 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
4980 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004981 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4983 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_ALERT | ERR_FATAL;
4985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 }
4987
Willy Tarreauade5ec42010-01-28 19:33:49 +01004988 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4989 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004990 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004991 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
4994 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004995 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4996 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004997 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004998 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005002 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5003 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005004 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005005 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005006 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005007 }
5008 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005009 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005010
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 if (curproxy == &defproxy) {
5012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005013 err_code |= ERR_ALERT | ERR_FATAL;
5014 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005015 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005016 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 if (*(args[1]) == 0) {
5020 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
5024
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005025 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
5026 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5027 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5028 file, linenum, args[0]);
5029 err_code |= ERR_ALERT | ERR_FATAL;
5030 goto out;
5031 }
5032 err_code |= warnif_cond_requires_req(cond, file, linenum);
5033 }
5034 else if (*args[2]) {
5035 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5036 file, linenum, args[0], args[2]);
5037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
5039 }
5040
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005041 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005042 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005043 wl->s = strdup(args[1]);
5044 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005045 }
5046 else if (!strcmp(args[0], "errorloc") ||
5047 !strcmp(args[0], "errorloc302") ||
5048 !strcmp(args[0], "errorloc303")) { /* error location */
5049 int errnum, errlen;
5050 char *err;
5051
Willy Tarreau977b8e42006-12-29 14:19:17 +01005052 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005054
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005056 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 }
5060
5061 errnum = atol(args[1]);
5062 if (!strcmp(args[0], "errorloc303")) {
5063 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5064 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5065 } else {
5066 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5067 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5068 }
5069
Willy Tarreau0f772532006-12-23 20:51:41 +01005070 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5071 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005072 chunk_destroy(&curproxy->errmsg[rc]);
5073 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005074 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005076 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005077
5078 if (rc >= HTTP_ERR_SIZE) {
5079 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5080 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 free(err);
5082 }
5083 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005084 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5085 int errnum, errlen, fd;
5086 char *err;
5087 struct stat stat;
5088
5089 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005091
5092 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005093 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005096 }
5097
5098 fd = open(args[2], O_RDONLY);
5099 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5100 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5101 file, linenum, args[2], args[1]);
5102 if (fd >= 0)
5103 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005106 }
5107
Willy Tarreau27a674e2009-08-17 07:23:33 +02005108 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005109 errlen = stat.st_size;
5110 } else {
5111 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005112 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005114 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005115 }
5116
5117 err = malloc(errlen); /* malloc() must succeed during parsing */
5118 errnum = read(fd, err, errlen);
5119 if (errnum != errlen) {
5120 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5121 file, linenum, args[2], args[1]);
5122 close(fd);
5123 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005126 }
5127 close(fd);
5128
5129 errnum = atol(args[1]);
5130 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5131 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005132 chunk_destroy(&curproxy->errmsg[rc]);
5133 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005134 break;
5135 }
5136 }
5137
5138 if (rc >= HTTP_ERR_SIZE) {
5139 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5140 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005142 free(err);
5143 }
5144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005146 struct cfg_kw_list *kwl;
5147 int index;
5148
5149 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5150 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5151 if (kwl->kw[index].section != CFG_LISTEN)
5152 continue;
5153 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5154 /* prepare error message just in case */
5155 snprintf(trash, sizeof(trash),
5156 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005157 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5158 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005159 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005162 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005163 else if (rc > 0) {
5164 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_WARN;
5166 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005167 }
Willy Tarreau93893792009-07-23 13:19:11 +02005168 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005169 }
5170 }
5171 }
5172
Willy Tarreau6daf3432008-01-22 16:44:08 +01005173 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005174 err_code |= ERR_ALERT | ERR_FATAL;
5175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
Willy Tarreau93893792009-07-23 13:19:11 +02005177 out:
5178 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005179}
5180
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005181int
5182cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5183{
5184
5185 int err_code = 0;
5186 const char *err;
5187
5188 if (!strcmp(args[0], "userlist")) { /* new userlist */
5189 struct userlist *newul;
5190
5191 if (!*args[1]) {
5192 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5193 file, linenum, args[0]);
5194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
5196 }
5197
5198 err = invalid_char(args[1]);
5199 if (err) {
5200 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5201 file, linenum, *err, args[0], args[1]);
5202 err_code |= ERR_ALERT | ERR_FATAL;
5203 goto out;
5204 }
5205
5206 for (newul = userlist; newul; newul = newul->next)
5207 if (!strcmp(newul->name, args[1])) {
5208 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5209 file, linenum, args[1]);
5210 err_code |= ERR_WARN;
5211 goto out;
5212 }
5213
5214 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5215 if (!newul) {
5216 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5217 err_code |= ERR_ALERT | ERR_ABORT;
5218 goto out;
5219 }
5220
5221 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5222 newul->name = strdup(args[1]);
5223
5224 if (!newul->groupusers | !newul->name) {
5225 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5226 err_code |= ERR_ALERT | ERR_ABORT;
5227 goto out;
5228 }
5229
5230 newul->next = userlist;
5231 userlist = newul;
5232
5233 } else if (!strcmp(args[0], "group")) { /* new group */
5234 int cur_arg, i;
5235 const char *err;
5236
5237 if (!*args[1]) {
5238 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5239 file, linenum, args[0]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243
5244 err = invalid_char(args[1]);
5245 if (err) {
5246 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5247 file, linenum, *err, args[0], args[1]);
5248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251
5252 for(i = 0; i < userlist->grpcnt; i++)
5253 if (!strcmp(userlist->groups[i], args[1])) {
5254 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5255 file, linenum, args[1], userlist->name);
5256 err_code |= ERR_ALERT;
5257 goto out;
5258 }
5259
5260 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5261 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5262 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
5266
5267 cur_arg = 2;
5268
5269 while (*args[cur_arg]) {
5270 if (!strcmp(args[cur_arg], "users")) {
5271 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5272 cur_arg += 2;
5273 continue;
5274 } else {
5275 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5276 file, linenum, args[0]);
5277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
5279 }
5280 }
5281
5282 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5283 } else if (!strcmp(args[0], "user")) { /* new user */
5284 struct auth_users *newuser;
5285 int cur_arg;
5286
5287 if (!*args[1]) {
5288 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5289 file, linenum, args[0]);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
5292 }
5293
5294 for (newuser = userlist->users; newuser; newuser = newuser->next)
5295 if (!strcmp(newuser->user, args[1])) {
5296 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5297 file, linenum, args[1], userlist->name);
5298 err_code |= ERR_ALERT;
5299 goto out;
5300 }
5301
5302 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5303 if (!newuser) {
5304 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5305 err_code |= ERR_ALERT | ERR_ABORT;
5306 goto out;
5307 }
5308
5309 newuser->user = strdup(args[1]);
5310
5311 newuser->next = userlist->users;
5312 userlist->users = newuser;
5313
5314 cur_arg = 2;
5315
5316 while (*args[cur_arg]) {
5317 if (!strcmp(args[cur_arg], "password")) {
5318#ifndef CONFIG_HAP_CRYPT
5319 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5320 file, linenum);
5321 err_code |= ERR_ALERT;
5322#endif
5323 newuser->pass = strdup(args[cur_arg + 1]);
5324 cur_arg += 2;
5325 continue;
5326 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5327 newuser->pass = strdup(args[cur_arg + 1]);
5328 newuser->flags |= AU_O_INSECURE;
5329 cur_arg += 2;
5330 continue;
5331 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005332 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005333 cur_arg += 2;
5334 continue;
5335 } else {
5336 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5337 file, linenum, args[0]);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341 }
5342 } else {
5343 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5344 err_code |= ERR_ALERT | ERR_FATAL;
5345 }
5346
5347out:
5348 return err_code;
5349}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350
5351/*
5352 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005353 * Returns the error code, 0 if OK, or any combination of :
5354 * - ERR_ABORT: must abort ASAP
5355 * - ERR_FATAL: we can continue parsing but not start the service
5356 * - ERR_WARN: a warning has been emitted
5357 * - ERR_ALERT: an alert has been emitted
5358 * Only the two first ones can stop processing, the two others are just
5359 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005361int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005363 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 FILE *f;
5365 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005367 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 if ((f=fopen(file,"r")) == NULL)
5370 return -1;
5371
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005372 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005373 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005374 char *end;
5375 char *args[MAX_LINE_ARGS + 1];
5376 char *line = thisline;
5377
Willy Tarreaubaaee002006-06-26 02:48:02 +02005378 linenum++;
5379
5380 end = line + strlen(line);
5381
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005382 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5383 /* Check if we reached the limit and the last char is not \n.
5384 * Watch out for the last line without the terminating '\n'!
5385 */
5386 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005387 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005388 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005389 }
5390
Willy Tarreaubaaee002006-06-26 02:48:02 +02005391 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005392 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 line++;
5394
5395 arg = 0;
5396 args[arg] = line;
5397
5398 while (*line && arg < MAX_LINE_ARGS) {
5399 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5400 * C equivalent value. Other combinations left unchanged (eg: \1).
5401 */
5402 if (*line == '\\') {
5403 int skip = 0;
5404 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5405 *line = line[1];
5406 skip = 1;
5407 }
5408 else if (line[1] == 'r') {
5409 *line = '\r';
5410 skip = 1;
5411 }
5412 else if (line[1] == 'n') {
5413 *line = '\n';
5414 skip = 1;
5415 }
5416 else if (line[1] == 't') {
5417 *line = '\t';
5418 skip = 1;
5419 }
5420 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005421 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005422 unsigned char hex1, hex2;
5423 hex1 = toupper(line[2]) - '0';
5424 hex2 = toupper(line[3]) - '0';
5425 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5426 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5427 *line = (hex1<<4) + hex2;
5428 skip = 3;
5429 }
5430 else {
5431 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005432 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
5434 }
5435 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005436 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 end -= skip;
5438 }
5439 line++;
5440 }
5441 else if (*line == '#' || *line == '\n' || *line == '\r') {
5442 /* end of string, end of loop */
5443 *line = 0;
5444 break;
5445 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005446 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005448 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005449 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 line++;
5451 args[++arg] = line;
5452 }
5453 else {
5454 line++;
5455 }
5456 }
5457
5458 /* empty line */
5459 if (!**args)
5460 continue;
5461
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005462 if (*line) {
5463 /* we had to stop due to too many args.
5464 * Let's terminate the string, print the offending part then cut the
5465 * last arg.
5466 */
5467 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5468 line++;
5469 *line = '\0';
5470
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005471 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005472 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005473 err_code |= ERR_ALERT | ERR_FATAL;
5474 args[arg] = line;
5475 }
5476
Willy Tarreau540abe42007-05-02 20:50:16 +02005477 /* zero out remaining args and ensure that at least one entry
5478 * is zeroed out.
5479 */
5480 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 args[arg] = line;
5482 }
5483
Willy Tarreau3842f002009-06-14 11:39:52 +02005484 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005485 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005486 char *tmp;
5487
Willy Tarreau3842f002009-06-14 11:39:52 +02005488 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005489 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005490 for (arg=0; *args[arg+1]; arg++)
5491 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005492 *tmp = '\0'; // fix the next arg to \0
5493 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005494 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005495 else if (!strcmp(args[0], "default")) {
5496 kwm = KWM_DEF;
5497 for (arg=0; *args[arg+1]; arg++)
5498 args[arg] = args[arg+1]; // shift args after inversion
5499 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005500
William Lallemand0f99e342011-10-12 17:50:54 +02005501 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5502 strcmp(args[0], "log") != 0) {
5503 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005504 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005505 }
5506
Willy Tarreau977b8e42006-12-29 14:19:17 +01005507 if (!strcmp(args[0], "listen") ||
5508 !strcmp(args[0], "frontend") ||
5509 !strcmp(args[0], "backend") ||
5510 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005511 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005513 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005514 cursection = strdup(args[0]);
5515 }
5516 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005518 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005519 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005520 }
5521 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005522 confsect = CFG_USERLIST;
5523 free(cursection);
5524 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005525 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005526 else if (!strcmp(args[0], "peers")) {
5527 confsect = CFG_PEERS;
5528 free(cursection);
5529 cursection = strdup(args[0]);
5530 }
5531
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 /* else it's a section keyword */
5533
5534 switch (confsect) {
5535 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005536 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 break;
5538 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005539 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005541 case CFG_USERLIST:
5542 err_code |= cfg_parse_users(file, linenum, args, kwm);
5543 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005544 case CFG_PEERS:
5545 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5546 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005547 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005548 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005549 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005551
5552 if (err_code & ERR_ABORT)
5553 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005555 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005556 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005558 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005559}
5560
Willy Tarreaubb925012009-07-23 13:36:36 +02005561/*
5562 * Returns the error code, 0 if OK, or any combination of :
5563 * - ERR_ABORT: must abort ASAP
5564 * - ERR_FATAL: we can continue parsing but not start the service
5565 * - ERR_WARN: a warning has been emitted
5566 * - ERR_ALERT: an alert has been emitted
5567 * Only the two first ones can stop processing, the two others are just
5568 * indicators.
5569 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005570int check_config_validity()
5571{
5572 int cfgerr = 0;
5573 struct proxy *curproxy = NULL;
5574 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005575 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005576 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005577 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578
5579 /*
5580 * Now, check for the integrity of all that we have collected.
5581 */
5582
5583 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005584 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005586 /* first, we will invert the proxy list order */
5587 curproxy = NULL;
5588 while (proxy) {
5589 struct proxy *next;
5590
5591 next = proxy->next;
5592 proxy->next = curproxy;
5593 curproxy = proxy;
5594 if (!next)
5595 break;
5596 proxy = next;
5597 }
5598
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005600 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005601 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005602 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005603 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005604 unsigned int next_id;
5605
5606 if (!curproxy->uuid) {
5607 /* proxy ID not set, use automatic numbering with first
5608 * spare entry starting with next_pxid.
5609 */
5610 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5611 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5612 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005613 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005614 next_pxid++;
5615
Willy Tarreau55ea7572007-06-17 19:56:27 +02005616
Willy Tarreaubaaee002006-06-26 02:48:02 +02005617 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005618 /* ensure we don't keep listeners uselessly bound */
5619 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 curproxy = curproxy->next;
5621 continue;
5622 }
5623
Willy Tarreauff01a212009-03-15 13:46:16 +01005624 switch (curproxy->mode) {
5625 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005626 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005627 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005628 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5629 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005630 cfgerr++;
5631 }
5632
5633 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005634 Warning("config : servers will be ignored for %s '%s'.\n",
5635 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005636 break;
5637
5638 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005639 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005640 break;
5641
5642 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005643 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005644 break;
5645 }
5646
5647 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005648 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5649 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 cfgerr++;
5651 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005652
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005653 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005654 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005655 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005656 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5657 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005658 cfgerr++;
5659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005661 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005662 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5663 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005664 cfgerr++;
5665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005667 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005668 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5669 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005670 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005671 }
5672 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005673 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005674 /* If no LB algo is set in a backend, and we're not in
5675 * transparent mode, dispatch mode nor proxy mode, we
5676 * want to use balance roundrobin by default.
5677 */
5678 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5679 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 }
5681 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005682
Willy Tarreau1620ec32011-08-06 17:05:02 +02005683 if (curproxy->options & PR_O_DISPATCH)
5684 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5685 else if (curproxy->options & PR_O_HTTP_PROXY)
5686 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5687 else if (curproxy->options & PR_O_TRANSP)
5688 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005689
Willy Tarreau1620ec32011-08-06 17:05:02 +02005690 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5691 if (curproxy->options & PR_O_DISABLE404) {
5692 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5693 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5694 err_code |= ERR_WARN;
5695 curproxy->options &= ~PR_O_DISABLE404;
5696 }
5697 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5698 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5699 "send-state", proxy_type_str(curproxy), curproxy->id);
5700 err_code |= ERR_WARN;
5701 curproxy->options &= ~PR_O2_CHK_SNDST;
5702 }
Willy Tarreauef781042010-01-27 11:53:01 +01005703 }
5704
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005705 /* if a default backend was specified, let's find it */
5706 if (curproxy->defbe.name) {
5707 struct proxy *target;
5708
Alex Williams96532db2009-11-01 21:27:13 -05005709 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005710 if (!target) {
5711 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5712 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005713 cfgerr++;
5714 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005715 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5716 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005717 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005718 } else {
5719 free(curproxy->defbe.name);
5720 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005721 /* we force the backend to be present on at least all of
5722 * the frontend's processes.
5723 */
5724 target->bind_proc = curproxy->bind_proc ?
5725 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005726
5727 /* Emit a warning if this proxy also has some servers */
5728 if (curproxy->srv) {
5729 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5730 curproxy->id);
5731 err_code |= ERR_WARN;
5732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 }
5734 }
5735
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005736 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005737 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5738 /* map jump target for ACT_SETBE in req_rep chain */
5739 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005740 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005741 struct proxy *target;
5742
Willy Tarreaua496b602006-12-17 23:15:24 +01005743 if (exp->action != ACT_SETBE)
5744 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005745
Alex Williams96532db2009-11-01 21:27:13 -05005746 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005747 if (!target) {
5748 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5749 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005750 cfgerr++;
5751 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005752 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5753 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005754 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005755 } else {
5756 free((void *)exp->replace);
5757 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005758 /* we force the backend to be present on at least all of
5759 * the frontend's processes.
5760 */
5761 target->bind_proc = curproxy->bind_proc ?
5762 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005763 }
5764 }
5765 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005766
5767 /* find the target proxy for 'use_backend' rules */
5768 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005769 struct proxy *target;
5770
Alex Williams96532db2009-11-01 21:27:13 -05005771 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005772
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005773 if (!target) {
5774 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5775 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005776 cfgerr++;
5777 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005778 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5779 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005780 cfgerr++;
5781 } else {
5782 free((void *)rule->be.name);
5783 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005784 /* we force the backend to be present on at least all of
5785 * the frontend's processes.
5786 */
5787 target->bind_proc = curproxy->bind_proc ?
5788 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005789 }
5790 }
5791
Emeric Brunb982a3d2010-01-04 15:45:53 +01005792 /* find the target table for 'stick' rules */
5793 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5794 struct proxy *target;
5795
Emeric Brun1d33b292010-01-04 15:47:17 +01005796 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5797 if (mrule->flags & STK_IS_STORE)
5798 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5799
Emeric Brunb982a3d2010-01-04 15:45:53 +01005800 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005801 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005802 else
5803 target = curproxy;
5804
5805 if (!target) {
5806 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5807 curproxy->id, mrule->table.name);
5808 cfgerr++;
5809 }
5810 else if (target->table.size == 0) {
5811 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5812 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5813 cfgerr++;
5814 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005815 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005816 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5817 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5818 cfgerr++;
5819 }
5820 else {
5821 free((void *)mrule->table.name);
5822 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005823 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005824 }
5825 }
5826
5827 /* find the target table for 'store response' rules */
5828 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5829 struct proxy *target;
5830
Emeric Brun1d33b292010-01-04 15:47:17 +01005831 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5832
Emeric Brunb982a3d2010-01-04 15:45:53 +01005833 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005834 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005835 else
5836 target = curproxy;
5837
5838 if (!target) {
5839 Alert("Proxy '%s': unable to find store table '%s'.\n",
5840 curproxy->id, mrule->table.name);
5841 cfgerr++;
5842 }
5843 else if (target->table.size == 0) {
5844 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5845 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5846 cfgerr++;
5847 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005848 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005849 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5850 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5851 cfgerr++;
5852 }
5853 else {
5854 free((void *)mrule->table.name);
5855 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005856 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005857 }
5858 }
5859
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005860 /* find the target table for 'tcp-request' layer 4 rules */
5861 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5862 struct proxy *target;
5863
Willy Tarreau56123282010-08-06 19:06:56 +02005864 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005865 continue;
5866
5867 if (trule->act_prm.trk_ctr.table.n)
5868 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5869 else
5870 target = curproxy;
5871
5872 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005873 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5874 curproxy->id, trule->act_prm.trk_ctr.table.n,
5875 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005876 cfgerr++;
5877 }
5878 else if (target->table.size == 0) {
5879 Alert("Proxy '%s': table '%s' used but not configured.\n",
5880 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5881 cfgerr++;
5882 }
5883 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005884 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 +02005885 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5886 cfgerr++;
5887 }
5888 else {
5889 free(trule->act_prm.trk_ctr.table.n);
5890 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005891 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005892 * to pass a list of counters to track and allocate them right here using
5893 * stktable_alloc_data_type().
5894 */
5895 }
5896 }
5897
Willy Tarreaud1f96522010-08-03 19:34:32 +02005898 /* find the target table for 'tcp-request' layer 6 rules */
5899 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5900 struct proxy *target;
5901
Willy Tarreau56123282010-08-06 19:06:56 +02005902 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005903 continue;
5904
5905 if (trule->act_prm.trk_ctr.table.n)
5906 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5907 else
5908 target = curproxy;
5909
5910 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005911 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5912 curproxy->id, trule->act_prm.trk_ctr.table.n,
5913 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005914 cfgerr++;
5915 }
5916 else if (target->table.size == 0) {
5917 Alert("Proxy '%s': table '%s' used but not configured.\n",
5918 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5919 cfgerr++;
5920 }
5921 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005922 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 +02005923 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5924 cfgerr++;
5925 }
5926 else {
5927 free(trule->act_prm.trk_ctr.table.n);
5928 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005929 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005930 * to pass a list of counters to track and allocate them right here using
5931 * stktable_alloc_data_type().
5932 */
5933 }
5934 }
5935
Emeric Brun32da3c42010-09-23 18:39:19 +02005936 if (curproxy->table.peers.name) {
5937 struct peers *curpeers = peers;
5938
5939 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5940 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5941 free((void *)curproxy->table.peers.name);
5942 curproxy->table.peers.p = peers;
5943 break;
5944 }
5945 }
5946
5947 if (!curpeers) {
5948 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5949 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005950 free((void *)curproxy->table.peers.name);
5951 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005952 cfgerr++;
5953 }
5954 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005955 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5956 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005957 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005958 cfgerr++;
5959 }
5960 }
5961
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005962 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005963 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005964 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5965 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5966 "proxy", curproxy->id);
5967 cfgerr++;
5968 goto out_uri_auth_compat;
5969 }
5970
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005971 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005972 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005973 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005974 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005975
Willy Tarreau95fa4692010-02-01 13:05:50 +01005976 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5977 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005978
5979 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005980 uri_auth_compat_req[i++] = "realm";
5981 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5982 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005983
Willy Tarreau95fa4692010-02-01 13:05:50 +01005984 uri_auth_compat_req[i++] = "unless";
5985 uri_auth_compat_req[i++] = "{";
5986 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5987 uri_auth_compat_req[i++] = "}";
5988 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005989
Willy Tarreauff011f22011-01-06 17:51:27 +01005990 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5991 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005992 cfgerr++;
5993 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005994 }
5995
Willy Tarreauff011f22011-01-06 17:51:27 +01005996 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005997
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005998 if (curproxy->uri_auth->auth_realm) {
5999 free(curproxy->uri_auth->auth_realm);
6000 curproxy->uri_auth->auth_realm = NULL;
6001 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006002
6003 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006004 }
6005out_uri_auth_compat:
6006
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006007 cfgerr += acl_find_targets(curproxy);
6008
Willy Tarreau2738a142006-07-08 17:28:09 +02006009 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006010 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006011 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006012 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006013 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006014 " | While not properly invalid, you will certainly encounter various problems\n"
6015 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006016 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006017 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006018 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006019 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006020
Willy Tarreau1fa31262007-12-03 00:36:16 +01006021 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6022 * We must still support older configurations, so let's find out whether those
6023 * parameters have been set or must be copied from contimeouts.
6024 */
6025 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006026 if (!curproxy->timeout.tarpit ||
6027 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006028 /* tarpit timeout not set. We search in the following order:
6029 * default.tarpit, curr.connect, default.connect.
6030 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006031 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006032 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006033 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006034 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006035 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006036 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006037 }
6038 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006039 (!curproxy->timeout.queue ||
6040 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006041 /* queue timeout not set. We search in the following order:
6042 * default.queue, curr.connect, default.connect.
6043 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006044 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006045 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006046 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006047 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006048 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006049 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006050 }
6051 }
6052
Willy Tarreau1620ec32011-08-06 17:05:02 +02006053 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006054 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6055 curproxy->check_req = (char *)malloc(curproxy->check_len);
6056 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006057 }
6058
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006059 /* The small pools required for the capture lists */
6060 if (curproxy->nb_req_cap)
6061 curproxy->req_cap_pool = create_pool("ptrcap",
6062 curproxy->nb_req_cap * sizeof(char *),
6063 MEM_F_SHARED);
6064 if (curproxy->nb_rsp_cap)
6065 curproxy->rsp_cap_pool = create_pool("ptrcap",
6066 curproxy->nb_rsp_cap * sizeof(char *),
6067 MEM_F_SHARED);
6068
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069 /* first, we will invert the servers list order */
6070 newsrv = NULL;
6071 while (curproxy->srv) {
6072 struct server *next;
6073
6074 next = curproxy->srv->next;
6075 curproxy->srv->next = newsrv;
6076 newsrv = curproxy->srv;
6077 if (!next)
6078 break;
6079 curproxy->srv = next;
6080 }
6081
Willy Tarreaudd701652010-05-25 23:03:02 +02006082 /* assign automatic UIDs to servers which don't have one yet */
6083 next_id = 1;
6084 newsrv = curproxy->srv;
6085 while (newsrv != NULL) {
6086 if (!newsrv->puid) {
6087 /* server ID not set, use automatic numbering with first
6088 * spare entry starting with next_svid.
6089 */
6090 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6091 newsrv->conf.id.key = newsrv->puid = next_id;
6092 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6093 }
6094 next_id++;
6095 newsrv = newsrv->next;
6096 }
6097
Willy Tarreau20697042007-11-15 23:26:18 +01006098 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006099 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006100
Willy Tarreau62c3be22012-01-20 13:12:32 +01006101 /*
6102 * If this server supports a maxconn parameter, it needs a dedicated
6103 * tasks to fill the emptied slots when a connection leaves.
6104 * Also, resolve deferred tracking dependency if needed.
6105 */
6106 newsrv = curproxy->srv;
6107 while (newsrv != NULL) {
6108 if (newsrv->minconn > newsrv->maxconn) {
6109 /* Only 'minconn' was specified, or it was higher than or equal
6110 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6111 * this will avoid further useless expensive computations.
6112 */
6113 newsrv->maxconn = newsrv->minconn;
6114 } else if (newsrv->maxconn && !newsrv->minconn) {
6115 /* minconn was not specified, so we set it to maxconn */
6116 newsrv->minconn = newsrv->maxconn;
6117 }
6118
6119 if (newsrv->trackit) {
6120 struct proxy *px;
6121 struct server *srv;
6122 char *pname, *sname;
6123
6124 pname = newsrv->trackit;
6125 sname = strrchr(pname, '/');
6126
6127 if (sname)
6128 *sname++ = '\0';
6129 else {
6130 sname = pname;
6131 pname = NULL;
6132 }
6133
6134 if (pname) {
6135 px = findproxy(pname, PR_CAP_BE);
6136 if (!px) {
6137 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6138 proxy_type_str(curproxy), curproxy->id,
6139 newsrv->id, pname);
6140 cfgerr++;
6141 goto next_srv;
6142 }
6143 } else
6144 px = curproxy;
6145
6146 srv = findserver(px, sname);
6147 if (!srv) {
6148 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6149 proxy_type_str(curproxy), curproxy->id,
6150 newsrv->id, sname);
6151 cfgerr++;
6152 goto next_srv;
6153 }
6154
6155 if (!(srv->state & SRV_CHECKED)) {
6156 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6157 "tracking as it does not have checks enabled.\n",
6158 proxy_type_str(curproxy), curproxy->id,
6159 newsrv->id, px->id, srv->id);
6160 cfgerr++;
6161 goto next_srv;
6162 }
6163
6164 if (curproxy != px &&
6165 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6166 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6167 "tracking: disable-on-404 option inconsistency.\n",
6168 proxy_type_str(curproxy), curproxy->id,
6169 newsrv->id, px->id, srv->id);
6170 cfgerr++;
6171 goto next_srv;
6172 }
6173
6174 /* if the other server is forced disabled, we have to do the same here */
6175 if (srv->state & SRV_MAINTAIN) {
6176 newsrv->state |= SRV_MAINTAIN;
6177 newsrv->state &= ~SRV_RUNNING;
6178 newsrv->health = 0;
6179 }
6180
6181 newsrv->track = srv;
6182 newsrv->tracknext = srv->tracknext;
6183 srv->tracknext = newsrv;
6184
6185 free(newsrv->trackit);
6186 newsrv->trackit = NULL;
6187 }
6188 next_srv:
6189 newsrv = newsrv->next;
6190 }
6191
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006192 /* We have to initialize the server lookup mechanism depending
6193 * on what LB algorithm was choosen.
6194 */
6195
6196 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6197 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6198 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006199 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6200 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6201 init_server_map(curproxy);
6202 } else {
6203 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6204 fwrr_init_server_groups(curproxy);
6205 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006206 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006207
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006208 case BE_LB_KIND_CB:
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006209 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006210 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006211 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006212
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006213 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006214 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6215 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6216 chash_init_server_tree(curproxy);
6217 } else {
6218 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6219 init_server_map(curproxy);
6220 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006221 break;
6222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006223
6224 if (curproxy->options & PR_O_LOGASAP)
6225 curproxy->to_log &= ~LW_BYTES;
6226
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006227 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006228 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006229 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6230 proxy_type_str(curproxy), curproxy->id);
6231 err_code |= ERR_WARN;
6232 }
6233
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006234 if (curproxy->mode != PR_MODE_HTTP) {
6235 int optnum;
6236
6237 if (curproxy->options & PR_O_COOK_ANY) {
6238 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6239 proxy_type_str(curproxy), curproxy->id);
6240 err_code |= ERR_WARN;
6241 }
6242
6243 if (curproxy->uri_auth) {
6244 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6245 proxy_type_str(curproxy), curproxy->id);
6246 err_code |= ERR_WARN;
6247 curproxy->uri_auth = NULL;
6248 }
6249
Willy Tarreau87cf5142011-08-19 22:57:24 +02006250 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006251 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6252 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6253 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006254 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006255 }
6256
6257 if (curproxy->options & PR_O_ORGTO) {
6258 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6259 "originalto", proxy_type_str(curproxy), curproxy->id);
6260 err_code |= ERR_WARN;
6261 curproxy->options &= ~PR_O_ORGTO;
6262 }
6263
6264 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6265 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6266 (curproxy->cap & cfg_opts[optnum].cap) &&
6267 (curproxy->options & cfg_opts[optnum].val)) {
6268 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6269 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6270 err_code |= ERR_WARN;
6271 curproxy->options &= ~cfg_opts[optnum].val;
6272 }
6273 }
6274
6275 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6276 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6277 (curproxy->cap & cfg_opts2[optnum].cap) &&
6278 (curproxy->options2 & cfg_opts2[optnum].val)) {
6279 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6280 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6281 err_code |= ERR_WARN;
6282 curproxy->options2 &= ~cfg_opts2[optnum].val;
6283 }
6284 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006285
Willy Tarreauefa5f512010-03-30 20:13:29 +02006286#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006287 if (curproxy->bind_hdr_occ) {
6288 curproxy->bind_hdr_occ = 0;
6289 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6290 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6291 err_code |= ERR_WARN;
6292 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006293#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006294 }
6295
Willy Tarreaubaaee002006-06-26 02:48:02 +02006296 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006297 * ensure that we're not cross-dressing a TCP server into HTTP.
6298 */
6299 newsrv = curproxy->srv;
6300 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006301 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006302 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6303 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006304 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006305 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006306
Willy Tarreau0cec3312011-10-31 13:49:26 +01006307 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6308 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6309 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6310 err_code |= ERR_WARN;
6311 }
6312
Willy Tarreauefa5f512010-03-30 20:13:29 +02006313#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006314 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6315 newsrv->bind_hdr_occ = 0;
6316 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6317 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6318 err_code |= ERR_WARN;
6319 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006320#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006321 newsrv = newsrv->next;
6322 }
6323
Willy Tarreauc1a21672009-08-16 22:37:44 +02006324 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006325 curproxy->accept = frontend_accept;
6326
Willy Tarreauc1a21672009-08-16 22:37:44 +02006327 if (curproxy->tcp_req.inspect_delay ||
6328 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006329 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006330
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006331 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006332 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006333 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006334 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006335
6336 /* both TCP and HTTP must check switching rules */
6337 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6338 }
6339
6340 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006341 if (curproxy->tcp_req.inspect_delay ||
6342 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6343 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6344
Emeric Brun97679e72010-09-23 17:56:44 +02006345 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6346 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6347
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006348 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006349 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006350 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006351 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006352
6353 /* If the backend does requires RDP cookie persistence, we have to
6354 * enable the corresponding analyser.
6355 */
6356 if (curproxy->options2 & PR_O2_RDPC_PRST)
6357 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6358 }
6359
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006360 listener = NULL;
6361 while (curproxy->listen) {
6362 struct listener *next;
6363
6364 next = curproxy->listen->next;
6365 curproxy->listen->next = listener;
6366 listener = curproxy->listen;
6367
6368 if (!next)
6369 break;
6370
6371 curproxy->listen = next;
6372 }
6373
Willy Tarreaue6b98942007-10-29 01:09:36 +01006374 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006375 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006376 listener = curproxy->listen;
6377 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006378 if (!listener->luid) {
6379 /* listener ID not set, use automatic numbering with first
6380 * spare entry starting with next_luid.
6381 */
6382 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6383 listener->conf.id.key = listener->luid = next_id;
6384 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006385 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006386 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006387
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006388 /* enable separate counters */
6389 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6390 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6391 if (!listener->name) {
6392 sprintf(trash, "sock-%d", listener->luid);
6393 listener->name = strdup(trash);
6394 }
6395 }
6396
Willy Tarreaue6b98942007-10-29 01:09:36 +01006397 if (curproxy->options & PR_O_TCP_NOLING)
6398 listener->options |= LI_O_NOLINGER;
6399 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006400 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006401 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006402 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006403 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006404 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006405 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006406
Willy Tarreau8a956912010-10-15 14:27:08 +02006407 if (listener->options & LI_O_ACC_PROXY)
6408 listener->analysers |= AN_REQ_DECODE_PROXY;
6409
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006410 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6411 listener->options |= LI_O_TCP_RULES;
6412
Willy Tarreaude3041d2010-05-31 10:56:17 +02006413 if (curproxy->mon_mask.s_addr)
6414 listener->options |= LI_O_CHK_MONNET;
6415
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006416 /* smart accept mode is automatic in HTTP mode */
6417 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6418 (curproxy->mode == PR_MODE_HTTP &&
6419 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6420 listener->options |= LI_O_NOQUICKACK;
6421
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006422 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006423 listener = listener->next;
6424 }
6425
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006426 /* Check multi-process mode compatibility for the current proxy */
6427 if (global.nbproc > 1) {
6428 int nbproc = 0;
6429 if (curproxy->bind_proc) {
6430 int proc;
6431 for (proc = 0; proc < global.nbproc; proc++) {
6432 if (curproxy->bind_proc & (1 << proc)) {
6433 nbproc++;
6434 }
6435 }
6436 } else {
6437 nbproc = global.nbproc;
6438 }
6439 if (curproxy->table.peers.name) {
6440 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6441 curproxy->id);
6442 cfgerr++;
6443 }
6444 if (nbproc > 1) {
6445 if (curproxy->uri_auth) {
6446 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6447 curproxy->id);
6448 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6449 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6450 curproxy->id);
6451 }
6452 }
6453 if (curproxy->appsession_name) {
6454 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6455 curproxy->id);
6456 }
6457 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6458 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6459 curproxy->id);
6460 }
6461 }
6462 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006463
6464 /* create the task associated with the proxy */
6465 curproxy->task = task_new();
6466 if (curproxy->task) {
6467 curproxy->task->context = curproxy;
6468 curproxy->task->process = manage_proxy;
6469 /* no need to queue, it will be done automatically if some
6470 * listener gets limited.
6471 */
6472 curproxy->task->expire = TICK_ETERNITY;
6473 } else {
6474 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6475 curproxy->id);
6476 cfgerr++;
6477 }
6478
Willy Tarreaubaaee002006-06-26 02:48:02 +02006479 curproxy = curproxy->next;
6480 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006481
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006482 /* Check multi-process mode compatibility */
6483 if (global.nbproc > 1) {
6484 if (global.stats_fe) {
6485 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6486 }
6487 }
6488
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006489 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6490 struct auth_users *curuser;
6491 int g;
6492
6493 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6494 unsigned int group_mask = 0;
6495 char *group = NULL;
6496
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006497 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006498 continue;
6499
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006500 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006501
6502 for (g = 0; g < curuserlist->grpcnt; g++)
6503 if (!strcmp(curuserlist->groups[g], group))
6504 break;
6505
6506 if (g == curuserlist->grpcnt) {
6507 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6508 curuserlist->name, group, curuser->user);
6509 err_code |= ERR_ALERT | ERR_FATAL;
6510 goto out;
6511 }
6512
6513 group_mask |= (1 << g);
6514 }
6515
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006516 free(curuser->u.groups);
6517 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006518 }
6519
6520 for (g = 0; g < curuserlist->grpcnt; g++) {
6521 char *user = NULL;
6522
6523 if (!curuserlist->groupusers[g])
6524 continue;
6525
6526 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6527 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6528 if (!strcmp(curuser->user, user))
6529 break;
6530
6531 if (!curuser) {
6532 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6533 curuserlist->name, user, curuserlist->groups[g]);
6534 err_code |= ERR_ALERT | ERR_FATAL;
6535 goto out;
6536 }
6537
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006538 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006539 }
6540
6541 free(curuserlist->groupusers[g]);
6542 }
6543
6544 free(curuserlist->groupusers);
6545
6546#ifdef DEBUG_AUTH
6547 for (g = 0; g < curuserlist->grpcnt; g++) {
6548 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6549
6550 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6551 if (curuser->group_mask & (1 << g))
6552 fprintf(stderr, " %s", curuser->user);
6553 }
6554
6555 fprintf(stderr, "\n");
6556 }
6557#endif
6558
Willy Tarreaufbb78422011-06-05 15:38:35 +02006559 }
6560
6561 /* automatically compute fullconn if not set. We must not do it in the
6562 * loop above because cross-references are not yet fully resolved.
6563 */
6564 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6565 /* If <fullconn> is not set, let's set it to 10% of the sum of
6566 * the possible incoming frontend's maxconns.
6567 */
6568 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6569 struct proxy *fe;
6570 int total = 0;
6571
6572 /* sum up the number of maxconns of frontends which
6573 * reference this backend at least once or which are
6574 * the same one ('listen').
6575 */
6576 for (fe = proxy; fe; fe = fe->next) {
6577 struct switching_rule *rule;
6578 struct hdr_exp *exp;
6579 int found = 0;
6580
6581 if (!(fe->cap & PR_CAP_FE))
6582 continue;
6583
6584 if (fe == curproxy) /* we're on a "listen" instance */
6585 found = 1;
6586
6587 if (fe->defbe.be == curproxy) /* "default_backend" */
6588 found = 1;
6589
6590 /* check if a "use_backend" rule matches */
6591 if (!found) {
6592 list_for_each_entry(rule, &fe->switching_rules, list) {
6593 if (rule->be.backend == curproxy) {
6594 found = 1;
6595 break;
6596 }
6597 }
6598 }
6599
6600 /* check if a "reqsetbe" rule matches */
6601 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6602 if (exp->action == ACT_SETBE &&
6603 (struct proxy *)exp->replace == curproxy) {
6604 found = 1;
6605 break;
6606 }
6607 }
6608
6609 /* now we've checked all possible ways to reference a backend
6610 * from a frontend.
6611 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006612 if (!found)
6613 continue;
6614 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006615 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006616 /* we have the sum of the maxconns in <total>. We only
6617 * keep 10% of that sum to set the default fullconn, with
6618 * a hard minimum of 1 (to avoid a divide by zero).
6619 */
6620 curproxy->fullconn = (total + 9) / 10;
6621 if (!curproxy->fullconn)
6622 curproxy->fullconn = 1;
6623 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006624 }
6625
Willy Tarreau056f5682010-06-06 15:51:11 +02006626 /* initialize stick-tables on backend capable proxies. This must not
6627 * be done earlier because the data size may be discovered while parsing
6628 * other proxies.
6629 */
6630 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006631 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006632
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006633 /*
6634 * Recount currently required checks.
6635 */
6636
6637 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6638 int optnum;
6639
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006640 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6641 if (curproxy->options & cfg_opts[optnum].val)
6642 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006643
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006644 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6645 if (curproxy->options2 & cfg_opts2[optnum].val)
6646 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006647 }
6648
Willy Tarreau122541c2011-09-07 21:24:49 +02006649 if (peers) {
6650 struct peers *curpeers = peers, **last;
6651 struct peer *p, *pb;
6652
6653 /* Remove all peers sections which don't have a valid listener.
6654 * This can happen when a peers section is never referenced and
6655 * does not contain a local peer.
6656 */
6657 last = &peers;
6658 while (*last) {
6659 curpeers = *last;
6660 if (curpeers->peers_fe) {
6661 last = &curpeers->next;
6662 continue;
6663 }
6664
6665 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6666 curpeers->id, localpeer);
6667
6668 p = curpeers->remote;
6669 while (p) {
6670 pb = p->next;
6671 free(p->id);
6672 free(p);
6673 p = pb;
6674 }
6675
6676 /* Destroy and unlink this curpeers section.
6677 * Note: curpeers is backed up into *last.
6678 */
6679 free(curpeers->id);
6680 curpeers = curpeers->next;
6681 free(*last);
6682 *last = curpeers;
6683 }
6684 }
6685
Willy Tarreauac1932d2011-10-24 19:14:41 +02006686 if (!global.tune.max_http_hdr)
6687 global.tune.max_http_hdr = MAX_HTTP_HDR;
6688
Willy Tarreau34eb6712011-10-24 18:15:04 +02006689 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006690 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006691 MEM_F_SHARED);
6692
Willy Tarreaubb925012009-07-23 13:36:36 +02006693 if (cfgerr > 0)
6694 err_code |= ERR_ALERT | ERR_FATAL;
6695 out:
6696 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006697}
6698
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006699/*
6700 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6701 * parsing sessions.
6702 */
6703void cfg_register_keywords(struct cfg_kw_list *kwl)
6704{
6705 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6706}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006707
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006708/*
6709 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6710 */
6711void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6712{
6713 LIST_DEL(&kwl->list);
6714 LIST_INIT(&kwl->list);
6715}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006716
6717/*
6718 * Local variables:
6719 * c-indent-level: 8
6720 * c-basic-offset: 8
6721 * End:
6722 */