blob: b881cd94d6a80960e6862bc91747785ac538687d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200164 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100165 { NULL, 0, 0, 0 }
166};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167
Willy Tarreau6daf3432008-01-22 16:44:08 +0100168static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
170int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100171int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200173/* List head of all known configuration keywords */
174static struct cfg_kw_list cfg_keywords = {
175 .list = LIST_HEAD_INIT(cfg_keywords.list)
176};
177
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178/*
179 * converts <str> to a list of listeners which are dynamically allocated.
180 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
181 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
182 * - <port> is a numerical port from 1 to 65535 ;
183 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
184 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200185 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100187static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200188{
189 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100190 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 int port, end;
192
193 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200194
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 while (next && *next) {
196 struct sockaddr_storage ss;
197
198 str = next;
199 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100200 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 *next++ = 0;
202 }
203
Emeric Bruned760922010-10-22 17:59:25 +0200204 if (*str == '/') {
205 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
206 /* so compute max path */
207 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
208 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209
Emeric Bruned760922010-10-22 17:59:25 +0200210 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100211 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
212 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200213 goto fail;
214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200217 ss.ss_family = AF_UNIX;
218 if (global.unix_bind.prefix) {
219 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
220 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 }
Emeric Bruned760922010-10-22 17:59:25 +0200222 else {
223 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
224 }
225 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 }
227 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100230 ss2 = str2sa_range(str, &port, &end);
231 if (!ss2) {
232 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
233 file, line, str);
234 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100237 if (!port) {
238 Alert("parsing [%s:%d] : missing port number: '%s'\n",
239 file, line, str);
240 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100243 /* OK the address looks correct */
244 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Emeric Bruned760922010-10-22 17:59:25 +0200246 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
248 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200249 goto fail;
250 }
251
252 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
254 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257 }
258
259 for (; port <= end; port++) {
260 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200261 l->next = curproxy->listen;
262 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
264 l->fd = -1;
265 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100266 l->state = LI_INIT;
267
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100268 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100270 tcpv4_add_listener(l);
271 }
Emeric Bruned760922010-10-22 17:59:25 +0200272 else if (ss.ss_family == AF_INET6) {
273 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
274 tcpv6_add_listener(l);
275 }
276 else {
277 l->perm.ux.gid = l->perm.ux.uid = -1;
278 l->perm.ux.mode = 0;
279 uxst_add_listener(l);
280 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200281
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200282 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100283 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284 } /* end for(port) */
285 } /* end while(next) */
286 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 fail:
289 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200290 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200291}
292
Willy Tarreau977b8e42006-12-29 14:19:17 +0100293/*
294 * Sends a warning if proxy <proxy> does not have at least one of the
295 * capabilities in <cap>. An optionnal <hint> may be added at the end
296 * of the warning to help the user. Returns 1 if a warning was emitted
297 * or 0 if the condition is valid.
298 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100299int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100300{
301 char *msg;
302
303 switch (cap) {
304 case PR_CAP_BE: msg = "no backend"; break;
305 case PR_CAP_FE: msg = "no frontend"; break;
306 case PR_CAP_RS: msg = "no ruleset"; break;
307 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
308 default: msg = "not enough"; break;
309 }
310
311 if (!(proxy->cap & cap)) {
312 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100313 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100314 return 1;
315 }
316 return 0;
317}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200318
Willy Tarreau61d18892009-03-31 10:49:21 +0200319/* Report a warning if a rule is placed after a 'block' rule.
320 * Return 1 if the warning has been emitted, otherwise 0.
321 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100322int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200323{
324 if (!LIST_ISEMPTY(&proxy->block_cond)) {
325 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
326 file, line, arg);
327 return 1;
328 }
329 return 0;
330}
331
332/* Report a warning if a rule is placed after a reqrewrite rule.
333 * Return 1 if the warning has been emitted, otherwise 0.
334 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100335int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200336{
337 if (proxy->req_exp) {
338 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
339 file, line, arg);
340 return 1;
341 }
342 return 0;
343}
344
345/* Report a warning if a rule is placed after a reqadd rule.
346 * Return 1 if the warning has been emitted, otherwise 0.
347 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100348int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200349{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100350 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200351 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
352 file, line, arg);
353 return 1;
354 }
355 return 0;
356}
357
358/* Report a warning if a rule is placed after a redirect rule.
359 * Return 1 if the warning has been emitted, otherwise 0.
360 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100361int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200362{
363 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
364 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
365 file, line, arg);
366 return 1;
367 }
368 return 0;
369}
370
371/* Report a warning if a rule is placed after a 'use_backend' rule.
372 * Return 1 if the warning has been emitted, otherwise 0.
373 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100374int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200375{
376 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
377 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
378 file, line, arg);
379 return 1;
380 }
381 return 0;
382}
383
384/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100385int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200386{
387 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
388 warnif_rule_after_reqadd(proxy, file, line, arg) ||
389 warnif_rule_after_redirect(proxy, file, line, arg) ||
390 warnif_rule_after_use_backend(proxy, file, line, arg);
391}
392
393/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100394int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200395{
396 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
397 warnif_rule_after_redirect(proxy, file, line, arg) ||
398 warnif_rule_after_use_backend(proxy, file, line, arg);
399}
400
401/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 return warnif_rule_after_redirect(proxy, file, line, arg) ||
405 warnif_rule_after_use_backend(proxy, file, line, arg);
406}
407
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100408/* Report it if a request ACL condition uses some response-only parameters. It
409 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
410 * Note that <cond> may be NULL and then will be ignored.
411 */
412static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
413{
414 struct acl *acl;
415
416 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
417 return 0;
418
419 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
420 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
421 file, line, acl ? acl->name : "(unknown)");
422 return ERR_WARN;
423}
424
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100425/* Report it if a request ACL condition uses some request-only volatile parameters.
426 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
427 * Note that <cond> may be NULL and then will be ignored.
428 */
429static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
430{
431 struct acl *acl;
432
433 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
434 return 0;
435
436 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
437 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
438 file, line, acl ? acl->name : "(unknown)");
439 return ERR_WARN;
440}
441
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100442
Willy Tarreaubaaee002006-06-26 02:48:02 +0200443/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200444 * parse a line in a <global> section. Returns the error code, 0 if OK, or
445 * any combination of :
446 * - ERR_ABORT: must abort ASAP
447 * - ERR_FATAL: we can continue parsing but not start the service
448 * - ERR_WARN: a warning has been emitted
449 * - ERR_ALERT: an alert has been emitted
450 * Only the two first ones can stop processing, the two others are just
451 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200453int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454{
Willy Tarreau058e9072009-07-20 09:30:05 +0200455 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456
457 if (!strcmp(args[0], "global")) { /* new section */
458 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200459 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460 }
461 else if (!strcmp(args[0], "daemon")) {
462 global.mode |= MODE_DAEMON;
463 }
464 else if (!strcmp(args[0], "debug")) {
465 global.mode |= MODE_DEBUG;
466 }
467 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100468 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200469 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200470 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100471 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200472 }
473 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100474 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100477 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100479 else if (!strcmp(args[0], "nosplice")) {
480 global.tune.options &= ~GTUNE_USE_SPLICE;
481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 else if (!strcmp(args[0], "quiet")) {
483 global.mode |= MODE_QUIET;
484 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200485 else if (!strcmp(args[0], "tune.maxpollevents")) {
486 if (global.tune.maxpollevents != 0) {
487 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200488 err_code |= ERR_ALERT;
489 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200490 }
491 if (*(args[1]) == 0) {
492 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 err_code |= ERR_ALERT | ERR_FATAL;
494 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 }
496 global.tune.maxpollevents = atol(args[1]);
497 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100498 else if (!strcmp(args[0], "tune.maxaccept")) {
499 if (global.tune.maxaccept != 0) {
500 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200501 err_code |= ERR_ALERT;
502 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100503 }
504 if (*(args[1]) == 0) {
505 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 }
509 global.tune.maxaccept = atol(args[1]);
510 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200511 else if (!strcmp(args[0], "tune.chksize")) {
512 if (*(args[1]) == 0) {
513 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
514 err_code |= ERR_ALERT | ERR_FATAL;
515 goto out;
516 }
517 global.tune.chksize = atol(args[1]);
518 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200519 else if (!strcmp(args[0], "tune.bufsize")) {
520 if (*(args[1]) == 0) {
521 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
522 err_code |= ERR_ALERT | ERR_FATAL;
523 goto out;
524 }
525 global.tune.bufsize = atol(args[1]);
526 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
527 global.tune.maxrewrite = global.tune.bufsize / 2;
528 }
529 else if (!strcmp(args[0], "tune.maxrewrite")) {
530 if (*(args[1]) == 0) {
531 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
532 err_code |= ERR_ALERT | ERR_FATAL;
533 goto out;
534 }
535 global.tune.maxrewrite = atol(args[1]);
536 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
537 global.tune.maxrewrite = global.tune.bufsize / 2;
538 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100539 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
540 if (global.tune.client_rcvbuf != 0) {
541 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
542 err_code |= ERR_ALERT;
543 goto out;
544 }
545 if (*(args[1]) == 0) {
546 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
547 err_code |= ERR_ALERT | ERR_FATAL;
548 goto out;
549 }
550 global.tune.client_rcvbuf = atol(args[1]);
551 }
552 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
553 if (global.tune.server_rcvbuf != 0) {
554 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
555 err_code |= ERR_ALERT;
556 goto out;
557 }
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.server_rcvbuf = atol(args[1]);
564 }
565 else if (!strcmp(args[0], "tune.sndbuf.client")) {
566 if (global.tune.client_sndbuf != 0) {
567 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT;
569 goto out;
570 }
571 if (*(args[1]) == 0) {
572 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT | ERR_FATAL;
574 goto out;
575 }
576 global.tune.client_sndbuf = atol(args[1]);
577 }
578 else if (!strcmp(args[0], "tune.sndbuf.server")) {
579 if (global.tune.server_sndbuf != 0) {
580 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT;
582 goto out;
583 }
584 if (*(args[1]) == 0) {
585 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
586 err_code |= ERR_ALERT | ERR_FATAL;
587 goto out;
588 }
589 global.tune.server_sndbuf = atol(args[1]);
590 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200591 else if (!strcmp(args[0], "tune.pipesize")) {
592 if (*(args[1]) == 0) {
593 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT | ERR_FATAL;
595 goto out;
596 }
597 global.tune.pipesize = atol(args[1]);
598 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200599 else if (!strcmp(args[0], "tune.http.maxhdr")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.max_http_hdr = atol(args[1]);
606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 else if (!strcmp(args[0], "uid")) {
608 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200609 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 err_code |= ERR_ALERT;
611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 }
613 if (*(args[1]) == 0) {
614 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT | ERR_FATAL;
616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 }
618 global.uid = atol(args[1]);
619 }
620 else if (!strcmp(args[0], "gid")) {
621 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200622 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200623 err_code |= ERR_ALERT;
624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 }
626 if (*(args[1]) == 0) {
627 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 }
631 global.gid = atol(args[1]);
632 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200633 /* user/group name handling */
634 else if (!strcmp(args[0], "user")) {
635 struct passwd *ha_user;
636 if (global.uid != 0) {
637 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200638 err_code |= ERR_ALERT;
639 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 }
641 errno = 0;
642 ha_user = getpwnam(args[1]);
643 if (ha_user != NULL) {
644 global.uid = (int)ha_user->pw_uid;
645 }
646 else {
647 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 else if (!strcmp(args[0], "group")) {
652 struct group *ha_group;
653 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200654 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200657 }
658 errno = 0;
659 ha_group = getgrnam(args[1]);
660 if (ha_group != NULL) {
661 global.gid = (int)ha_group->gr_gid;
662 }
663 else {
664 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200665 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200666 }
667 }
668 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 else if (!strcmp(args[0], "nbproc")) {
670 if (global.nbproc != 0) {
671 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT;
673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
675 if (*(args[1]) == 0) {
676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT | ERR_FATAL;
678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200679 }
680 global.nbproc = atol(args[1]);
681 }
682 else if (!strcmp(args[0], "maxconn")) {
683 if (global.maxconn != 0) {
684 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200685 err_code |= ERR_ALERT;
686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 }
688 if (*(args[1]) == 0) {
689 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200690 err_code |= ERR_ALERT | ERR_FATAL;
691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200692 }
693 global.maxconn = atol(args[1]);
694#ifdef SYSTEM_MAXCONN
695 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
696 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
697 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 }
700#endif /* SYSTEM_MAXCONN */
701 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200702 else if (!strcmp(args[0], "maxconnrate")) {
703 if (global.cps_lim != 0) {
704 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
705 err_code |= ERR_ALERT;
706 goto out;
707 }
708 if (*(args[1]) == 0) {
709 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713 global.cps_lim = atol(args[1]);
714 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100715 else if (!strcmp(args[0], "maxpipes")) {
716 if (global.maxpipes != 0) {
717 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200718 err_code |= ERR_ALERT;
719 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100720 }
721 if (*(args[1]) == 0) {
722 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT | ERR_FATAL;
724 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100725 }
726 global.maxpipes = atol(args[1]);
727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200728 else if (!strcmp(args[0], "ulimit-n")) {
729 if (global.rlimit_nofile != 0) {
730 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200731 err_code |= ERR_ALERT;
732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200733 }
734 if (*(args[1]) == 0) {
735 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739 global.rlimit_nofile = atol(args[1]);
740 }
741 else if (!strcmp(args[0], "chroot")) {
742 if (global.chroot != NULL) {
743 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200744 err_code |= ERR_ALERT;
745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 }
747 if (*(args[1]) == 0) {
748 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200749 err_code |= ERR_ALERT | ERR_FATAL;
750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200751 }
752 global.chroot = strdup(args[1]);
753 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200754 else if (!strcmp(args[0], "description")) {
755 int i, len=0;
756 char *d;
757
758 if (!*args[1]) {
759 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
760 file, linenum, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764
765 for(i=1; *args[i]; i++)
766 len += strlen(args[i])+1;
767
768 if (global.desc)
769 free(global.desc);
770
771 global.desc = d = (char *)calloc(1, len);
772
773 d += sprintf(d, "%s", args[1]);
774 for(i=2; *args[i]; i++)
775 d += sprintf(d, " %s", args[i]);
776 }
777 else if (!strcmp(args[0], "node")) {
778 int i;
779 char c;
780
781 for (i=0; args[1][i]; i++) {
782 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100783 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
784 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200785 break;
786 }
787
788 if (!i || args[1][i]) {
789 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
790 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
791 file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795
796 if (global.node)
797 free(global.node);
798
799 global.node = strdup(args[1]);
800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200801 else if (!strcmp(args[0], "pidfile")) {
802 if (global.pidfile != NULL) {
803 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200804 err_code |= ERR_ALERT;
805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 }
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 }
812 global.pidfile = strdup(args[1]);
813 }
Emeric Bruned760922010-10-22 17:59:25 +0200814 else if (!strcmp(args[0], "unix-bind")) {
815 int cur_arg = 1;
816 while (*(args[cur_arg])) {
817 if (!strcmp(args[cur_arg], "prefix")) {
818 if (global.unix_bind.prefix != NULL) {
819 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
820 err_code |= ERR_ALERT;
821 cur_arg += 2;
822 continue;
823 }
824
825 if (*(args[cur_arg+1]) == 0) {
826 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.unix_bind.prefix = strdup(args[cur_arg+1]);
831 cur_arg += 2;
832 continue;
833 }
834
835 if (!strcmp(args[cur_arg], "mode")) {
836
837 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "uid")) {
843
844 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
845 cur_arg += 2;
846 continue;
847 }
848
849 if (!strcmp(args[cur_arg], "gid")) {
850
851 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
852 cur_arg += 2;
853 continue;
854 }
855
856 if (!strcmp(args[cur_arg], "user")) {
857 struct passwd *user;
858
859 user = getpwnam(args[cur_arg + 1]);
860 if (!user) {
861 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
862 file, linenum, args[0], args[cur_arg + 1 ]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866
867 global.unix_bind.ux.uid = user->pw_uid;
868 cur_arg += 2;
869 continue;
870 }
871
872 if (!strcmp(args[cur_arg], "group")) {
873 struct group *group;
874
875 group = getgrnam(args[cur_arg + 1]);
876 if (!group) {
877 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
878 file, linenum, args[0], args[cur_arg + 1 ]);
879 err_code |= ERR_ALERT | ERR_FATAL;
880 goto out;
881 }
882
883 global.unix_bind.ux.gid = group->gr_gid;
884 cur_arg += 2;
885 continue;
886 }
887
Willy Tarreaub48f9582011-09-05 01:17:06 +0200888 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200889 file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 }
William Lallemand0f99e342011-10-12 17:50:54 +0200894 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
895 /* delete previous herited or defined syslog servers */
896 struct logsrv *back;
897 struct logsrv *tmp;
898
899 if (*(args[1]) != 0) {
900 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
901 err_code |= ERR_ALERT | ERR_FATAL;
902 goto out;
903 }
904
905 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
906 LIST_DEL(&tmp->list);
907 free(tmp);
908 }
909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200911 struct logsrv *logsrv;
912
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 if (*(args[1]) == 0 || *(args[2]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 }
William Lallemand0f99e342011-10-12 17:50:54 +0200918
919 logsrv = calloc(1, sizeof(struct logsrv));
920
921 logsrv->facility = get_log_facility(args[2]);
922 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200925 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927
William Lallemand0f99e342011-10-12 17:50:54 +0200928 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200930 logsrv->level = get_log_level(args[3]);
931 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200934 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 }
937
William Lallemand0f99e342011-10-12 17:50:54 +0200938 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200939 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200940 logsrv->minlvl = get_log_level(args[4]);
941 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200942 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200944 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200945 }
946 }
947
Robert Tsai81ae1952007-12-05 10:47:29 +0100948 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100949 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100950 if (!sk) {
951 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100952 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100953 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200954 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100955 goto out;
956 }
William Lallemand0f99e342011-10-12 17:50:54 +0200957 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100958 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100959 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100960 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
962 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200963 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100964 goto out;
965 }
William Lallemand0f99e342011-10-12 17:50:54 +0200966 logsrv->addr = *sk;
967 if (!get_host_port(&logsrv->addr))
968 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970
William Lallemand0f99e342011-10-12 17:50:54 +0200971 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200972 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100973 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
974 char *name;
975 int len;
976
977 if (global.log_send_hostname != NULL) {
978 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT;
980 goto out;
981 }
982
983 if (*(args[1]))
984 name = args[1];
985 else
986 name = hostname;
987
988 len = strlen(name);
989
990 /* We'll add a space after the name to respect the log format */
991 free(global.log_send_hostname);
992 global.log_send_hostname = malloc(len + 2);
993 snprintf(global.log_send_hostname, len + 2, "%s ", name);
994 }
Kevinm48936af2010-12-22 16:08:21 +0000995 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
996 if (*(args[1]) == 0) {
997 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001 free(global.log_tag);
1002 global.log_tag = strdup(args[1]);
1003 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001004 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1005 if (global.spread_checks != 0) {
1006 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_ALERT;
1008 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001009 }
1010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001014 }
1015 global.spread_checks = atol(args[1]);
1016 if (global.spread_checks < 0 || global.spread_checks > 50) {
1017 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 }
1021 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001022 struct cfg_kw_list *kwl;
1023 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001024 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001025
1026 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1027 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1028 if (kwl->kw[index].section != CFG_GLOBAL)
1029 continue;
1030 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1031 /* prepare error message just in case */
1032 snprintf(trash, sizeof(trash),
1033 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001034 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1035 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001036 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001037 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001038 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001039 else if (rc > 0) {
1040 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001041 err_code |= ERR_WARN;
1042 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001043 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001045 }
1046 }
1047 }
1048
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001052
Willy Tarreau058e9072009-07-20 09:30:05 +02001053 out:
1054 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055}
1056
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001057void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001059 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001060 defproxy.mode = PR_MODE_TCP;
1061 defproxy.state = PR_STNEW;
1062 defproxy.maxconn = cfg_maxpconn;
1063 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001064
1065 defproxy.defsrv.inter = DEF_CHKINTR;
1066 defproxy.defsrv.fastinter = 0;
1067 defproxy.defsrv.downinter = 0;
1068 defproxy.defsrv.rise = DEF_RISETIME;
1069 defproxy.defsrv.fall = DEF_FALLTIME;
1070 defproxy.defsrv.check_port = 0;
1071 defproxy.defsrv.maxqueue = 0;
1072 defproxy.defsrv.minconn = 0;
1073 defproxy.defsrv.maxconn = 0;
1074 defproxy.defsrv.slowstart = 0;
1075 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1076 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1077 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001078}
1079
Willy Tarreauade5ec42010-01-28 19:33:49 +01001080
1081static int create_cond_regex_rule(const char *file, int line,
1082 struct proxy *px, int dir, int action, int flags,
1083 const char *cmd, const char *reg, const char *repl,
1084 const char **cond_start)
1085{
1086 regex_t *preg = NULL;
1087 const char *err;
1088 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001089 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001090
1091 if (px == &defproxy) {
1092 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto err;
1095 }
1096
1097 if (*reg == 0) {
1098 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1099 err_code |= ERR_ALERT | ERR_FATAL;
1100 goto err;
1101 }
1102
1103 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1104 err_code |= ERR_WARN;
1105
Willy Tarreau5321c422010-01-28 20:35:13 +01001106 if (cond_start &&
1107 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1108 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1109 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1110 file, line, cmd);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto err;
1113 }
1114 }
1115 else if (cond_start && **cond_start) {
1116 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1117 file, line, cmd, *cond_start);
1118 err_code |= ERR_ALERT | ERR_FATAL;
1119 goto err;
1120 }
1121
1122 if (dir == ACL_DIR_REQ)
1123 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001124 else
1125 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001126
Willy Tarreauade5ec42010-01-28 19:33:49 +01001127 preg = calloc(1, sizeof(regex_t));
1128 if (!preg) {
1129 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1130 err_code = ERR_ALERT | ERR_FATAL;
1131 goto err;
1132 }
1133
1134 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1135 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1136 err_code = ERR_ALERT | ERR_FATAL;
1137 goto err;
1138 }
1139
1140 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001141 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001142 if (repl && err) {
1143 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1144 file, line, cmd, *err);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto err;
1147 }
1148
1149 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1150 err_code |= ERR_WARN;
1151
1152 return err_code;
1153 err:
1154 free(preg);
1155 return err_code;
1156}
1157
Willy Tarreaubaaee002006-06-26 02:48:02 +02001158/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001159 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001160 * Returns the error code, 0 if OK, or any combination of :
1161 * - ERR_ABORT: must abort ASAP
1162 * - ERR_FATAL: we can continue parsing but not start the service
1163 * - ERR_WARN: a warning has been emitted
1164 * - ERR_ALERT: an alert has been emitted
1165 * Only the two first ones can stop processing, the two others are just
1166 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001168int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1169{
1170 static struct peers *curpeers = NULL;
1171 struct peer *newpeer = NULL;
1172 const char *err;
1173 int err_code = 0;
1174
1175 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1176
1177 err = invalid_char(args[1]);
1178 if (err) {
1179 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1180 file, linenum, *err, args[0], args[1]);
1181 err_code |= ERR_ALERT | ERR_FATAL;
1182 }
1183
1184 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1185 /*
1186 * If there are two proxies with the same name only following
1187 * combinations are allowed:
1188 */
1189 if (strcmp(curpeers->id, args[1]) == 0) {
1190 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1191 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1192 err_code |= ERR_WARN;
1193 }
1194 }
1195
1196 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1197 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1198 err_code |= ERR_ALERT | ERR_ABORT;
1199 goto out;
1200 }
1201
1202 curpeers->next = peers;
1203 peers = curpeers;
1204 curpeers->conf.file = file;
1205 curpeers->conf.line = linenum;
1206 curpeers->last_change = now.tv_sec;
1207 curpeers->id = strdup(args[1]);
1208 }
1209 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1210 char *rport, *raddr;
1211 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001212 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001213
1214 if (!*args[2]) {
1215 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1216 file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220
1221 err = invalid_char(args[1]);
1222 if (err) {
1223 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1224 file, linenum, *err, args[1]);
1225 err_code |= ERR_ALERT | ERR_FATAL;
1226 goto out;
1227 }
1228
1229 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1230 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1231 err_code |= ERR_ALERT | ERR_ABORT;
1232 goto out;
1233 }
1234
1235 /* the peers are linked backwards first */
1236 curpeers->count++;
1237 newpeer->next = curpeers->remote;
1238 curpeers->remote = newpeer;
1239 newpeer->peers = curpeers;
1240 newpeer->conf.file = file;
1241 newpeer->conf.line = linenum;
1242
1243 newpeer->last_change = now.tv_sec;
1244 newpeer->id = strdup(args[1]);
1245
1246 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001247 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001248 if (rport) {
1249 *rport++ = 0;
1250 realport = atol(rport);
1251 }
1252 if (!realport) {
1253 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1254 err_code |= ERR_ALERT | ERR_FATAL;
1255 goto out;
1256 }
1257
Willy Tarreaufab5a432011-03-04 15:31:53 +01001258 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001259 free(raddr);
1260 if (!sk) {
1261 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1262 err_code |= ERR_ALERT | ERR_FATAL;
1263 goto out;
1264 }
1265 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001266 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001267
1268 if (strcmp(newpeer->id, localpeer) == 0) {
1269 /* Current is local peer, it define a frontend */
1270 newpeer->local = 1;
1271
1272 if (!curpeers->peers_fe) {
1273 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1275 err_code |= ERR_ALERT | ERR_ABORT;
1276 goto out;
1277 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001278
Willy Tarreau237250c2011-07-29 01:49:03 +02001279 init_new_proxy(curpeers->peers_fe);
1280 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001281
1282 curpeers->peers_fe->last_change = now.tv_sec;
1283 curpeers->peers_fe->id = strdup(args[1]);
1284 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001285 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001286 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1287 curpeers->peers_fe->timeout.connect = 5000;
1288 curpeers->peers_fe->accept = peer_accept;
1289 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001290 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001291 err_code |= ERR_FATAL;
1292 goto out;
1293 }
1294 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1295 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1296 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1297 curpeers->peers_fe->listen->accept = session_accept;
1298 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1299 curpeers->peers_fe->listen->handler = process_session;
1300 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001301 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1302 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001303 }
1304 }
1305 } /* neither "peer" nor "peers" */
1306 else if (*args[0] != 0) {
1307 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
1310 }
1311
1312out:
1313 return err_code;
1314}
1315
1316
Willy Tarreau3842f002009-06-14 11:39:52 +02001317int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001318{
1319 static struct proxy *curproxy = NULL;
1320 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001321 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001322 int rc;
1323 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001324 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001325 struct acl_cond *cond = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02001326 struct logsrv *tmp;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327
Willy Tarreau977b8e42006-12-29 14:19:17 +01001328 if (!strcmp(args[0], "listen"))
1329 rc = PR_CAP_LISTEN;
1330 else if (!strcmp(args[0], "frontend"))
1331 rc = PR_CAP_FE | PR_CAP_RS;
1332 else if (!strcmp(args[0], "backend"))
1333 rc = PR_CAP_BE | PR_CAP_RS;
1334 else if (!strcmp(args[0], "ruleset"))
1335 rc = PR_CAP_RS;
1336 else
1337 rc = PR_CAP_NONE;
1338
1339 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340 if (!*args[1]) {
1341 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1342 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1343 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001344 err_code |= ERR_ALERT | ERR_ABORT;
1345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001347
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001348 err = invalid_char(args[1]);
1349 if (err) {
1350 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1351 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001352 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001353 }
1354
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001355 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1356 /*
1357 * If there are two proxies with the same name only following
1358 * combinations are allowed:
1359 *
1360 * listen backend frontend ruleset
1361 * listen - - - -
1362 * backend - - OK -
1363 * frontend - OK - -
1364 * ruleset - - - -
1365 */
1366
1367 if (!strcmp(curproxy->id, args[1]) &&
1368 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1369 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001370 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1371 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1372 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001373 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001374 }
1375 }
1376
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1378 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001379 err_code |= ERR_ALERT | ERR_ABORT;
1380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001381 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001382
Willy Tarreau97cb7802010-01-03 20:23:58 +01001383 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 curproxy->next = proxy;
1385 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001386 curproxy->conf.file = file;
1387 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001388 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001390 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391
1392 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001393 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001394 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001395 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001396 err_code |= ERR_FATAL;
1397 goto out;
1398 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001399 new = curproxy->listen;
1400 while (new != last) {
1401 new->conf.file = file;
1402 new->conf.line = linenum;
1403 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001404 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001406 }
1407
1408 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001409 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001410 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001411
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001414 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001415 curproxy->no_options = defproxy.no_options;
1416 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001417 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001418 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001419 curproxy->except_net = defproxy.except_net;
1420 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001421 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001422 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001424 if (defproxy.fwdfor_hdr_len) {
1425 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1426 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1427 }
1428
Willy Tarreaub86db342009-11-30 11:50:16 +01001429 if (defproxy.orgto_hdr_len) {
1430 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1431 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1432 }
1433
Mark Lamourinec2247f02012-01-04 13:02:01 -05001434 if (defproxy.server_id_hdr_len) {
1435 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1436 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1437 }
1438
Willy Tarreau977b8e42006-12-29 14:19:17 +01001439 if (curproxy->cap & PR_CAP_FE) {
1440 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001441 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001442 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001443
1444 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001445 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1446 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001447
1448 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450
Willy Tarreau977b8e42006-12-29 14:19:17 +01001451 if (curproxy->cap & PR_CAP_BE) {
1452 curproxy->fullconn = defproxy.fullconn;
1453 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001455 if (defproxy.check_req) {
1456 curproxy->check_req = calloc(1, defproxy.check_len);
1457 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1458 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001459 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001461 if (defproxy.expect_str) {
1462 curproxy->expect_str = strdup(defproxy.expect_str);
1463 if (defproxy.expect_regex) {
1464 /* note: this regex is known to be valid */
1465 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1466 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1467 }
1468 }
1469
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470 if (defproxy.cookie_name)
1471 curproxy->cookie_name = strdup(defproxy.cookie_name);
1472 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001473 if (defproxy.cookie_domain)
1474 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001475
Willy Tarreau31936852010-10-06 16:59:56 +02001476 if (defproxy.cookie_maxidle)
1477 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1478
1479 if (defproxy.cookie_maxlife)
1480 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1481
Emeric Brun647caf12009-06-30 17:57:00 +02001482 if (defproxy.rdp_cookie_name)
1483 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1484 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1485
Willy Tarreau01732802007-11-01 22:48:15 +01001486 if (defproxy.url_param_name)
1487 curproxy->url_param_name = strdup(defproxy.url_param_name);
1488 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001489
Benoitaffb4812009-03-25 13:02:10 +01001490 if (defproxy.hh_name)
1491 curproxy->hh_name = strdup(defproxy.hh_name);
1492 curproxy->hh_len = defproxy.hh_len;
1493 curproxy->hh_match_domain = defproxy.hh_match_domain;
1494
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001495 if (defproxy.iface_name)
1496 curproxy->iface_name = strdup(defproxy.iface_name);
1497 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001500 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001501 if (defproxy.capture_name)
1502 curproxy->capture_name = strdup(defproxy.capture_name);
1503 curproxy->capture_namelen = defproxy.capture_namelen;
1504 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506
Willy Tarreau977b8e42006-12-29 14:19:17 +01001507 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001508 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001509 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001510 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001511 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001512 curproxy->uri_auth = defproxy.uri_auth;
1513 curproxy->mon_net = defproxy.mon_net;
1514 curproxy->mon_mask = defproxy.mon_mask;
1515 if (defproxy.monitor_uri)
1516 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1517 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001518 if (defproxy.defbe.name)
1519 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001520 }
1521
1522 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001523 curproxy->timeout.connect = defproxy.timeout.connect;
1524 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001525 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001526 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001527 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001528 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001529 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001530 curproxy->source_addr = defproxy.source_addr;
1531 }
1532
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001534
1535 /* copy default logsrvs to curproxy */
1536 list_for_each_entry(tmp, &defproxy.logsrvs, list) {
1537 struct logsrv *node = malloc(sizeof(struct logsrv));
1538 memcpy(node, tmp, sizeof(struct logsrv));
1539 LIST_INIT(&node->list);
1540 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1541 }
1542
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001544 curproxy->conf.used_listener_id = EB_ROOT;
1545 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001546
Willy Tarreau93893792009-07-23 13:19:11 +02001547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548 }
1549 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1550 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001551 /* FIXME-20070101: we should do this too at the end of the
1552 * config parsing to free all default values.
1553 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001554 free(defproxy.check_req);
1555 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001556 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001557 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001558 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001559 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001560 free(defproxy.capture_name);
1561 free(defproxy.monitor_uri);
1562 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001563 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001564 free(defproxy.fwdfor_hdr_name);
1565 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001566 free(defproxy.orgto_hdr_name);
1567 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001568 free(defproxy.server_id_hdr_name);
1569 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001570 free(defproxy.expect_str);
1571 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001572
Willy Tarreaua534fea2008-08-03 12:19:50 +02001573 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001574 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001575
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576 /* we cannot free uri_auth because it might already be used */
1577 init_default_instance();
1578 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 }
1582 else if (curproxy == NULL) {
1583 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
1587
Willy Tarreau977b8e42006-12-29 14:19:17 +01001588
1589 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001591 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001592 int cur_arg;
1593
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 if (curproxy == &defproxy) {
1595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001599 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001600 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601
Emeric Bruned760922010-10-22 17:59:25 +02001602 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001603 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 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 Tarreaub1e52e82008-01-13 14:49:51 +01001608
1609 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001610
1611 /* NOTE: the following line might create several listeners if there
1612 * are comma-separated IPs or port ranges. So all further processing
1613 * will have to be applied to all listeners created after last_listen.
1614 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001615 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001616 err_code |= ERR_ALERT | ERR_FATAL;
1617 goto out;
1618 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001619
Willy Tarreau90a570f2009-10-04 20:54:54 +02001620 new_listen = curproxy->listen;
1621 while (new_listen != last_listen) {
1622 new_listen->conf.file = file;
1623 new_listen->conf.line = linenum;
1624 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001625 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001626 }
1627
Emeric Bruned760922010-10-22 17:59:25 +02001628 /* Set default global rights and owner for unix bind */
1629 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1630 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1631 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001632 cur_arg = 2;
1633 while (*(args[cur_arg])) {
1634 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1635#ifdef SO_BINDTODEVICE
1636 struct listener *l;
1637
Emeric Bruned760922010-10-22 17:59:25 +02001638 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1639 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1640 file, linenum, args[0], args[cur_arg]);
1641 err_code |= ERR_ALERT | ERR_FATAL;
1642 goto out;
1643 }
1644
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001645 if (!*args[cur_arg + 1]) {
1646 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1647 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001650 }
1651
1652 for (l = curproxy->listen; l != last_listen; l = l->next)
1653 l->interface = strdup(args[cur_arg + 1]);
1654
1655 global.last_checks |= LSTCHK_NETADM;
1656
1657 cur_arg += 2;
1658 continue;
1659#else
1660 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1661 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001664#endif
1665 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001666 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1667#ifdef TCP_MAXSEG
1668 struct listener *l;
1669 int mss;
1670
Emeric Bruned760922010-10-22 17:59:25 +02001671 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1672 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1673 file, linenum, args[0], args[cur_arg]);
1674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
1676 }
1677
Willy Tarreaube1b9182009-06-14 18:48:19 +02001678 if (!*args[cur_arg + 1]) {
1679 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1680 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001681 err_code |= ERR_ALERT | ERR_FATAL;
1682 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001683 }
1684
Willy Tarreau48a7e722010-12-24 15:26:39 +01001685 mss = atoi(args[cur_arg + 1]);
1686 if (!mss || abs(mss) > 65535) {
1687 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001688 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001691 }
1692
1693 for (l = curproxy->listen; l != last_listen; l = l->next)
1694 l->maxseg = mss;
1695
1696 cur_arg += 2;
1697 continue;
1698#else
1699 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1700 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001701 err_code |= ERR_ALERT | ERR_FATAL;
1702 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001703#endif
1704 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001705
1706 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1707#ifdef TCP_DEFER_ACCEPT
1708 struct listener *l;
1709
1710 for (l = curproxy->listen; l != last_listen; l = l->next)
1711 l->options |= LI_O_DEF_ACCEPT;
1712
1713 cur_arg ++;
1714 continue;
1715#else
1716 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1717 file, linenum, args[0], args[cur_arg]);
1718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
1720#endif
1721 }
1722
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001723 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001724#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001725 struct listener *l;
1726
Emeric Bruned760922010-10-22 17:59:25 +02001727 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1728 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1729 file, linenum, args[0], args[cur_arg]);
1730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
1732 }
1733
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734 for (l = curproxy->listen; l != last_listen; l = l->next)
1735 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001736
1737 cur_arg ++;
1738 continue;
1739#else
1740 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1741 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001742 err_code |= ERR_ALERT | ERR_FATAL;
1743 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001744#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001745 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001746
Willy Tarreau8a956912010-10-15 14:27:08 +02001747 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1748 struct listener *l;
1749
1750 for (l = curproxy->listen; l != last_listen; l = l->next)
1751 l->options |= LI_O_ACC_PROXY;
1752
1753 cur_arg ++;
1754 continue;
1755 }
1756
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001757 if (!strcmp(args[cur_arg], "name")) {
1758 struct listener *l;
1759
1760 for (l = curproxy->listen; l != last_listen; l = l->next)
1761 l->name = strdup(args[cur_arg + 1]);
1762
1763 cur_arg += 2;
1764 continue;
1765 }
1766
1767 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001768 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001769 struct listener *l;
1770
1771 if (curproxy->listen->next != last_listen) {
1772 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1773 file, linenum, args[cur_arg]);
1774 err_code |= ERR_ALERT | ERR_FATAL;
1775 goto out;
1776 }
1777
1778 if (!*args[cur_arg + 1]) {
1779 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1780 file, linenum, args[cur_arg]);
1781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001786 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001787
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001788 if (curproxy->listen->luid <= 0) {
1789 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001790 file, linenum);
1791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
1793 }
1794
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001795 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1796 if (node) {
1797 l = container_of(node, struct listener, conf.id);
1798 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1799 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 goto out;
1802 }
1803 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1804
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001805 cur_arg += 2;
1806 continue;
1807 }
1808
Emeric Bruned760922010-10-22 17:59:25 +02001809 if (!strcmp(args[cur_arg], "mode")) {
1810
1811 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1812 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1813 file, linenum, args[0], args[cur_arg]);
1814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817
1818 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1819
1820 cur_arg += 2;
1821 continue;
1822 }
1823
1824 if (!strcmp(args[cur_arg], "uid")) {
1825
1826 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1827 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1828 file, linenum, args[0], args[cur_arg]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831 }
1832
1833 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1834 cur_arg += 2;
1835 continue;
1836 }
1837
1838 if (!strcmp(args[cur_arg], "gid")) {
1839
1840 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1841 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1842 file, linenum, args[0], args[cur_arg]);
1843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
1845 }
1846
1847 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1848 cur_arg += 2;
1849 continue;
1850 }
1851
1852 if (!strcmp(args[cur_arg], "user")) {
1853 struct passwd *user;
1854
1855 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1856 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1857 file, linenum, args[0], args[cur_arg]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 user = getpwnam(args[cur_arg + 1]);
1862 if (!user) {
1863 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1864 file, linenum, args[0], args[cur_arg + 1 ]);
1865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
1867 }
1868
1869 curproxy->listen->perm.ux.uid = user->pw_uid;
1870 cur_arg += 2;
1871 continue;
1872 }
1873
1874 if (!strcmp(args[cur_arg], "group")) {
1875 struct group *group;
1876
1877 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1878 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1879 file, linenum, args[0], args[cur_arg]);
1880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
1882 }
1883 group = getgrnam(args[cur_arg + 1]);
1884 if (!group) {
1885 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1886 file, linenum, args[0], args[cur_arg + 1 ]);
1887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
1889 }
1890
1891 curproxy->listen->perm.ux.gid = group->gr_gid;
1892 cur_arg += 2;
1893 continue;
1894 }
1895
Willy Tarreaub48f9582011-09-05 01:17:06 +02001896 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 +01001897 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001900 }
Willy Tarreau93893792009-07-23 13:19:11 +02001901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902 }
1903 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1904 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1905 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1906 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001907 err_code |= ERR_ALERT | ERR_FATAL;
1908 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001910 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001911 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001912
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 /* flush useless bits */
1914 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001916 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001917 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001918 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001919 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920
Willy Tarreau1c47f852006-07-09 08:22:27 +02001921 if (!*args[1]) {
1922 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1923 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001924 err_code |= ERR_ALERT | ERR_FATAL;
1925 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001926 }
1927
Willy Tarreaua534fea2008-08-03 12:19:50 +02001928 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001929 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001930 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001931 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001932 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1933
Willy Tarreau93893792009-07-23 13:19:11 +02001934 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001935 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1937 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1938 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1939 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1940 else {
1941 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
1943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 }
1945 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001946 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001947 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001948
1949 if (curproxy == &defproxy) {
1950 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1951 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001954 }
1955
1956 if (!*args[1]) {
1957 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1958 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_ALERT | ERR_FATAL;
1960 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001961 }
1962
1963 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001964 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001965
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001966 if (curproxy->uuid <= 0) {
1967 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001968 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001969 err_code |= ERR_ALERT | ERR_FATAL;
1970 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001971 }
1972
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001973 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1974 if (node) {
1975 struct proxy *target = container_of(node, struct proxy, conf.id);
1976 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1977 file, linenum, proxy_type_str(curproxy), curproxy->id,
1978 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1979 err_code |= ERR_ALERT | ERR_FATAL;
1980 goto out;
1981 }
1982 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001983 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001984 else if (!strcmp(args[0], "description")) {
1985 int i, len=0;
1986 char *d;
1987
Cyril Bonté99ed3272010-01-24 23:29:44 +01001988 if (curproxy == &defproxy) {
1989 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1990 file, linenum, args[0]);
1991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
1993 }
1994
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001995 if (!*args[1]) {
1996 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1997 file, linenum, args[0]);
1998 return -1;
1999 }
2000
2001 for(i=1; *args[i]; i++)
2002 len += strlen(args[i])+1;
2003
2004 d = (char *)calloc(1, len);
2005 curproxy->desc = d;
2006
2007 d += sprintf(d, "%s", args[1]);
2008 for(i=2; *args[i]; i++)
2009 d += sprintf(d, " %s", args[i]);
2010
2011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2013 curproxy->state = PR_STSTOPPED;
2014 }
2015 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2016 curproxy->state = PR_STNEW;
2017 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002018 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2019 int cur_arg = 1;
2020 unsigned int set = 0;
2021
2022 while (*args[cur_arg]) {
2023 int u;
2024 if (strcmp(args[cur_arg], "all") == 0) {
2025 set = 0;
2026 break;
2027 }
2028 else if (strcmp(args[cur_arg], "odd") == 0) {
2029 set |= 0x55555555;
2030 }
2031 else if (strcmp(args[cur_arg], "even") == 0) {
2032 set |= 0xAAAAAAAA;
2033 }
2034 else {
2035 u = str2uic(args[cur_arg]);
2036 if (u < 1 || u > 32) {
2037 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002041 }
2042 if (u > global.nbproc) {
2043 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2044 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002045 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002046 }
2047 set |= 1 << (u - 1);
2048 }
2049 cur_arg++;
2050 }
2051 curproxy->bind_proc = set;
2052 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002053 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002054 if (curproxy == &defproxy) {
2055 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002056 err_code |= ERR_ALERT | ERR_FATAL;
2057 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002058 }
2059
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002060 err = invalid_char(args[1]);
2061 if (err) {
2062 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2063 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002064 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002065 }
2066
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002067 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2068 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2069 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002070 err_code |= ERR_ALERT | ERR_FATAL;
2071 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002072 }
2073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2075 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076
Willy Tarreau977b8e42006-12-29 14:19:17 +01002077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 if (*(args[1]) == 0) {
2081 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2082 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002086
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002087 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002088 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002089 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002090 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002091 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 curproxy->cookie_name = strdup(args[1]);
2093 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002094
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 cur_arg = 2;
2096 while (*(args[cur_arg])) {
2097 if (!strcmp(args[cur_arg], "rewrite")) {
2098 curproxy->options |= PR_O_COOK_RW;
2099 }
2100 else if (!strcmp(args[cur_arg], "indirect")) {
2101 curproxy->options |= PR_O_COOK_IND;
2102 }
2103 else if (!strcmp(args[cur_arg], "insert")) {
2104 curproxy->options |= PR_O_COOK_INS;
2105 }
2106 else if (!strcmp(args[cur_arg], "nocache")) {
2107 curproxy->options |= PR_O_COOK_NOC;
2108 }
2109 else if (!strcmp(args[cur_arg], "postonly")) {
2110 curproxy->options |= PR_O_COOK_POST;
2111 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002112 else if (!strcmp(args[cur_arg], "preserve")) {
2113 curproxy->options2 |= PR_O2_COOK_PSV;
2114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 else if (!strcmp(args[cur_arg], "prefix")) {
2116 curproxy->options |= PR_O_COOK_PFX;
2117 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002118 else if (!strcmp(args[cur_arg], "domain")) {
2119 if (!*args[cur_arg + 1]) {
2120 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2121 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002122 err_code |= ERR_ALERT | ERR_FATAL;
2123 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002124 }
2125
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002126 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002127 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002128 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2129 " dots nor does not start with a dot."
2130 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002131 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002132 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002133 }
2134
2135 err = invalid_domainchar(args[cur_arg + 1]);
2136 if (err) {
2137 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2138 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002139 err_code |= ERR_ALERT | ERR_FATAL;
2140 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002141 }
2142
Willy Tarreau68a897b2009-12-03 23:28:34 +01002143 if (!curproxy->cookie_domain) {
2144 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2145 } else {
2146 /* one domain was already specified, add another one by
2147 * building the string which will be returned along with
2148 * the cookie.
2149 */
2150 char *new_ptr;
2151 int new_len = strlen(curproxy->cookie_domain) +
2152 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2153 new_ptr = malloc(new_len);
2154 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2155 free(curproxy->cookie_domain);
2156 curproxy->cookie_domain = new_ptr;
2157 }
Willy Tarreau31936852010-10-06 16:59:56 +02002158 cur_arg++;
2159 }
2160 else if (!strcmp(args[cur_arg], "maxidle")) {
2161 unsigned int maxidle;
2162 const char *res;
2163
2164 if (!*args[cur_arg + 1]) {
2165 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2166 file, linenum, args[cur_arg]);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
2171 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2172 if (res) {
2173 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2174 file, linenum, *res, args[cur_arg]);
2175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
2177 }
2178 curproxy->cookie_maxidle = maxidle;
2179 cur_arg++;
2180 }
2181 else if (!strcmp(args[cur_arg], "maxlife")) {
2182 unsigned int maxlife;
2183 const char *res;
2184
2185 if (!*args[cur_arg + 1]) {
2186 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2187 file, linenum, args[cur_arg]);
2188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
2190 }
2191
2192 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2193 if (res) {
2194 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2195 file, linenum, *res, args[cur_arg]);
2196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
2198 }
2199 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002200 cur_arg++;
2201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002202 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002203 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 +02002204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002205 err_code |= ERR_ALERT | ERR_FATAL;
2206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 }
2208 cur_arg++;
2209 }
2210 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2211 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2212 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002213 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002214 }
2215
2216 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2217 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2218 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002219 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002221
2222 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2223 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2224 file, linenum);
2225 err_code |= ERR_ALERT | ERR_FATAL;
2226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002228 else if (!strcmp(args[0], "persist")) { /* persist */
2229 if (*(args[1]) == 0) {
2230 Alert("parsing [%s:%d] : missing persist method.\n",
2231 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002234 }
2235
2236 if (!strncmp(args[1], "rdp-cookie", 10)) {
2237 curproxy->options2 |= PR_O2_RDPC_PRST;
2238
Emeric Brunb982a3d2010-01-04 15:45:53 +01002239 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002240 const char *beg, *end;
2241
2242 beg = args[1] + 11;
2243 end = strchr(beg, ')');
2244
2245 if (!end || end == beg) {
2246 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2247 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002250 }
2251
2252 free(curproxy->rdp_cookie_name);
2253 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2254 curproxy->rdp_cookie_len = end-beg;
2255 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002256 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002257 free(curproxy->rdp_cookie_name);
2258 curproxy->rdp_cookie_name = strdup("msts");
2259 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2260 }
2261 else { /* syntax */
2262 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2263 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002264 err_code |= ERR_ALERT | ERR_FATAL;
2265 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002266 }
2267 }
2268 else {
2269 Alert("parsing [%s:%d] : unknown persist method.\n",
2270 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002273 }
2274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002276 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2280 err_code |= ERR_ALERT | ERR_FATAL;
2281 goto out;
2282 }
2283
Willy Tarreau977b8e42006-12-29 14:19:17 +01002284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002286
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002288 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 }
2293 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002294 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 curproxy->appsession_name = strdup(args[1]);
2296 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2297 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002298 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2299 if (err) {
2300 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2301 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002304 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002305 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002306
Willy Tarreau51041c72007-09-09 21:56:53 +02002307 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2308 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002309 err_code |= ERR_ALERT | ERR_ABORT;
2310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002312
2313 cur_arg = 6;
2314 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002315 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2316 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002317 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002318 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002319 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002320 } else if (!strcmp(args[cur_arg], "prefix")) {
2321 curproxy->options2 |= PR_O2_AS_PFX;
2322 } else if (!strcmp(args[cur_arg], "mode")) {
2323 if (!*args[cur_arg + 1]) {
2324 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2325 file, linenum, args[0], args[cur_arg]);
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329
2330 cur_arg++;
2331 if (!strcmp(args[cur_arg], "query-string")) {
2332 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2333 curproxy->options2 |= PR_O2_AS_M_QS;
2334 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2335 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2336 curproxy->options2 |= PR_O2_AS_M_PP;
2337 } else {
2338 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2339 err_code |= ERR_ALERT | ERR_FATAL;
2340 goto out;
2341 }
2342 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002343 cur_arg++;
2344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 } /* Url App Session */
2346 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002347 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002349
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002351 if (curproxy == &defproxy) {
2352 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
2355 }
2356
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 if (*(args[4]) == 0) {
2358 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2359 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002360 err_code |= ERR_ALERT | ERR_FATAL;
2361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002363 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 curproxy->capture_name = strdup(args[2]);
2365 curproxy->capture_namelen = strlen(curproxy->capture_name);
2366 curproxy->capture_len = atol(args[4]);
2367 if (curproxy->capture_len >= CAPTURE_LEN) {
2368 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2369 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 curproxy->capture_len = CAPTURE_LEN - 1;
2372 }
2373 curproxy->to_log |= LW_COOKIE;
2374 }
2375 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2376 struct cap_hdr *hdr;
2377
2378 if (curproxy == &defproxy) {
2379 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 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 }
2383
2384 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2385 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2386 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 }
2390
2391 hdr = calloc(sizeof(struct cap_hdr), 1);
2392 hdr->next = curproxy->req_cap;
2393 hdr->name = strdup(args[3]);
2394 hdr->namelen = strlen(args[3]);
2395 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002396 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 hdr->index = curproxy->nb_req_cap++;
2398 curproxy->req_cap = hdr;
2399 curproxy->to_log |= LW_REQHDR;
2400 }
2401 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2402 struct cap_hdr *hdr;
2403
2404 if (curproxy == &defproxy) {
2405 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 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }
2409
2410 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2411 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2412 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 }
2416 hdr = calloc(sizeof(struct cap_hdr), 1);
2417 hdr->next = curproxy->rsp_cap;
2418 hdr->name = strdup(args[3]);
2419 hdr->namelen = strlen(args[3]);
2420 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002421 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 hdr->index = curproxy->nb_rsp_cap++;
2423 curproxy->rsp_cap = hdr;
2424 curproxy->to_log |= LW_RSPHDR;
2425 }
2426 else {
2427 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2428 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 }
2432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002434 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002436
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 if (*(args[1]) == 0) {
2438 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2439 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443 curproxy->conn_retries = atol(args[1]);
2444 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002445 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002446 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002447
2448 if (curproxy == &defproxy) {
2449 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
2452 }
2453
Willy Tarreauff011f22011-01-06 17:51:27 +01002454 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 +01002455 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2456 file, linenum, args[0]);
2457 err_code |= ERR_WARN;
2458 }
2459
Willy Tarreauff011f22011-01-06 17:51:27 +01002460 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002461
Willy Tarreauff011f22011-01-06 17:51:27 +01002462 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002463 err_code |= ERR_ALERT | ERR_ABORT;
2464 goto out;
2465 }
2466
Willy Tarreauff011f22011-01-06 17:51:27 +01002467 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2468 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002469 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002470 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2471 /* set the header name and length into the proxy structure */
2472 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2473 err_code |= ERR_WARN;
2474
2475 if (!*args[1]) {
2476 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2477 file, linenum, args[0]);
2478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
2480 }
2481
2482 /* set the desired header name */
2483 free(curproxy->server_id_hdr_name);
2484 curproxy->server_id_hdr_name = strdup(args[1]);
2485 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2486 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002487 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002488 if (curproxy == &defproxy) {
2489 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002492 }
2493
Willy Tarreauef6494c2010-01-28 17:12:36 +01002494 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002495 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2496 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002499 }
2500
Willy Tarreauef6494c2010-01-28 17:12:36 +01002501 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002502 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2503 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002506 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002507
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002508 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002509 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002510 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002511 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002512 struct redirect_rule *rule;
2513 int cur_arg;
2514 int type = REDIRECT_TYPE_NONE;
2515 int code = 302;
2516 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002517 char *cookie = NULL;
2518 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002519 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002520
Cyril Bonté99ed3272010-01-24 23:29:44 +01002521 if (curproxy == &defproxy) {
2522 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
2525 }
2526
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002527 cur_arg = 1;
2528 while (*(args[cur_arg])) {
2529 if (!strcmp(args[cur_arg], "location")) {
2530 if (!*args[cur_arg + 1]) {
2531 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2532 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002535 }
2536
2537 type = REDIRECT_TYPE_LOCATION;
2538 cur_arg++;
2539 destination = args[cur_arg];
2540 }
2541 else if (!strcmp(args[cur_arg], "prefix")) {
2542 if (!*args[cur_arg + 1]) {
2543 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2544 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002547 }
2548
2549 type = REDIRECT_TYPE_PREFIX;
2550 cur_arg++;
2551 destination = args[cur_arg];
2552 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002553 else if (!strcmp(args[cur_arg], "set-cookie")) {
2554 if (!*args[cur_arg + 1]) {
2555 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2556 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002559 }
2560
2561 cur_arg++;
2562 cookie = args[cur_arg];
2563 cookie_set = 1;
2564 }
2565 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2566 if (!*args[cur_arg + 1]) {
2567 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2568 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_FATAL;
2570 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002571 }
2572
2573 cur_arg++;
2574 cookie = args[cur_arg];
2575 cookie_set = 0;
2576 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002577 else if (!strcmp(args[cur_arg],"code")) {
2578 if (!*args[cur_arg + 1]) {
2579 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2580 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002583 }
2584 cur_arg++;
2585 code = atol(args[cur_arg]);
2586 if (code < 301 || code > 303) {
2587 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2588 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002589 err_code |= ERR_ALERT | ERR_FATAL;
2590 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002591 }
2592 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002593 else if (!strcmp(args[cur_arg],"drop-query")) {
2594 flags |= REDIRECT_FLAG_DROP_QS;
2595 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002596 else if (!strcmp(args[cur_arg],"append-slash")) {
2597 flags |= REDIRECT_FLAG_APPEND_SLASH;
2598 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002599 else if (strcmp(args[cur_arg], "if") == 0 ||
2600 strcmp(args[cur_arg], "unless") == 0) {
2601 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2602 if (!cond) {
2603 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2604 file, linenum, args[0]);
2605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
2607 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002608 break;
2609 }
2610 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002611 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 +02002612 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002615 }
2616 cur_arg++;
2617 }
2618
2619 if (type == REDIRECT_TYPE_NONE) {
2620 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2621 file, linenum, args[0]);
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
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002626 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2627 rule->cond = cond;
2628 rule->rdr_str = strdup(destination);
2629 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002630 if (cookie) {
2631 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002632 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002633 */
2634 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002635 if (cookie_set) {
2636 rule->cookie_str = malloc(rule->cookie_len + 10);
2637 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2638 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2639 rule->cookie_len += 9;
2640 } else {
2641 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002642 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002643 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2644 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002645 }
2646 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002647 rule->type = type;
2648 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002649 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002650 LIST_INIT(&rule->list);
2651 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002652 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2653 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002654 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002655 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002656 struct switching_rule *rule;
2657
Willy Tarreaub099aca2008-10-12 17:26:37 +02002658 if (curproxy == &defproxy) {
2659 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002662 }
2663
Willy Tarreau55ea7572007-06-17 19:56:27 +02002664 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002665 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002666
2667 if (*(args[1]) == 0) {
2668 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002671 }
2672
Willy Tarreauef6494c2010-01-28 17:12:36 +01002673 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002674 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2675 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002678 }
2679
Willy Tarreauef6494c2010-01-28 17:12:36 +01002680 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002681 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002682 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002685 }
2686
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002687 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002688
Willy Tarreau55ea7572007-06-17 19:56:27 +02002689 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2690 rule->cond = cond;
2691 rule->be.name = strdup(args[1]);
2692 LIST_INIT(&rule->list);
2693 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2694 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002695 else if ((!strcmp(args[0], "force-persist")) ||
2696 (!strcmp(args[0], "ignore-persist"))) {
2697 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002698
2699 if (curproxy == &defproxy) {
2700 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
2703 }
2704
2705 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2706 err_code |= ERR_WARN;
2707
Willy Tarreauef6494c2010-01-28 17:12:36 +01002708 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002709 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2710 file, linenum, args[0]);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714
Willy Tarreauef6494c2010-01-28 17:12:36 +01002715 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002716 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2717 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
2720 }
2721
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002722 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002723
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002724 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002725 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002726 if (!strcmp(args[0], "force-persist")) {
2727 rule->type = PERSIST_TYPE_FORCE;
2728 } else {
2729 rule->type = PERSIST_TYPE_IGNORE;
2730 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002731 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002732 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002733 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002734 else if (!strcmp(args[0], "stick-table")) {
2735 int myidx = 1;
2736
Emeric Brun32da3c42010-09-23 18:39:19 +02002737 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002738 curproxy->table.type = (unsigned int)-1;
2739 while (*args[myidx]) {
2740 const char *err;
2741
2742 if (strcmp(args[myidx], "size") == 0) {
2743 myidx++;
2744 if (!*(args[myidx])) {
2745 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2746 file, linenum, args[myidx-1]);
2747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
2750 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2751 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2752 file, linenum, *err, args[myidx-1]);
2753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
2755 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002756 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002757 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002758 else if (strcmp(args[myidx], "peers") == 0) {
2759 myidx++;
2760 if (!*(args[myidx])) {
2761 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2762 file, linenum, args[myidx-1]);
2763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
2766 curproxy->table.peers.name = strdup(args[myidx++]);
2767 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002768 else if (strcmp(args[myidx], "expire") == 0) {
2769 myidx++;
2770 if (!*(args[myidx])) {
2771 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2772 file, linenum, args[myidx-1]);
2773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
2775 }
2776 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2777 if (err) {
2778 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2779 file, linenum, *err, args[myidx-1]);
2780 err_code |= ERR_ALERT | ERR_FATAL;
2781 goto out;
2782 }
2783 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002784 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002785 }
2786 else if (strcmp(args[myidx], "nopurge") == 0) {
2787 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002788 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002789 }
2790 else if (strcmp(args[myidx], "type") == 0) {
2791 myidx++;
2792 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2793 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2794 file, linenum, args[myidx]);
2795 err_code |= ERR_ALERT | ERR_FATAL;
2796 goto out;
2797 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002798 /* myidx already points to next arg */
2799 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002800 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002801 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002802 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002803
2804 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002805 nw = args[myidx];
2806 while (*nw) {
2807 /* the "store" keyword supports a comma-separated list */
2808 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002809 sa = NULL; /* store arg */
2810 while (*nw && *nw != ',') {
2811 if (*nw == '(') {
2812 *nw = 0;
2813 sa = ++nw;
2814 while (*nw != ')') {
2815 if (!*nw) {
2816 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2817 file, linenum, args[0], cw);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
2820 }
2821 nw++;
2822 }
2823 *nw = '\0';
2824 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002825 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002826 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002827 if (*nw)
2828 *nw++ = '\0';
2829 type = stktable_get_data_type(cw);
2830 if (type < 0) {
2831 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2832 file, linenum, args[0], cw);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
Willy Tarreauac782882010-06-20 10:41:54 +02002836
2837 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2838 switch (err) {
2839 case PE_NONE: break;
2840 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002841 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2842 file, linenum, args[0], cw);
2843 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002844 break;
2845
2846 case PE_ARG_MISSING:
2847 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2848 file, linenum, args[0], cw);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851
2852 case PE_ARG_NOT_USED:
2853 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2854 file, linenum, args[0], cw);
2855 err_code |= ERR_ALERT | ERR_FATAL;
2856 goto out;
2857
2858 default:
2859 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2860 file, linenum, args[0], cw);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002863 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002864 }
2865 myidx++;
2866 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002867 else {
2868 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2869 file, linenum, args[myidx]);
2870 err_code |= ERR_ALERT | ERR_FATAL;
2871 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002872 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002873 }
2874
2875 if (!curproxy->table.size) {
2876 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2877 file, linenum);
2878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
2880 }
2881
2882 if (curproxy->table.type == (unsigned int)-1) {
2883 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2884 file, linenum);
2885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
2887 }
2888 }
2889 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002890 struct sticking_rule *rule;
2891 struct pattern_expr *expr;
2892 int myidx = 0;
2893 const char *name = NULL;
2894 int flags;
2895
2896 if (curproxy == &defproxy) {
2897 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900 }
2901
2902 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2903 err_code |= ERR_WARN;
2904 goto out;
2905 }
2906
2907 myidx++;
2908 if ((strcmp(args[myidx], "store") == 0) ||
2909 (strcmp(args[myidx], "store-request") == 0)) {
2910 myidx++;
2911 flags = STK_IS_STORE;
2912 }
2913 else if (strcmp(args[myidx], "store-response") == 0) {
2914 myidx++;
2915 flags = STK_IS_STORE | STK_ON_RSP;
2916 }
2917 else if (strcmp(args[myidx], "match") == 0) {
2918 myidx++;
2919 flags = STK_IS_MATCH;
2920 }
2921 else if (strcmp(args[myidx], "on") == 0) {
2922 myidx++;
2923 flags = STK_IS_MATCH | STK_IS_STORE;
2924 }
2925 else {
2926 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930
2931 if (*(args[myidx]) == 0) {
2932 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936
Emeric Brun485479d2010-09-23 18:02:19 +02002937 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002939 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
2943
2944 if (flags & STK_ON_RSP) {
2945 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2946 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2947 file, linenum, args[0], expr->fetch->kw);
2948 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002949 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002950 goto out;
2951 }
2952 } else {
2953 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2954 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2955 file, linenum, args[0], expr->fetch->kw);
2956 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002957 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002958 goto out;
2959 }
2960 }
2961
2962 if (strcmp(args[myidx], "table") == 0) {
2963 myidx++;
2964 name = args[myidx++];
2965 }
2966
Willy Tarreauef6494c2010-01-28 17:12:36 +01002967 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2968 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002969 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2970 file, linenum, args[0]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002972 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002973 goto out;
2974 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002975 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002976 else if (*(args[myidx])) {
2977 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2978 file, linenum, args[0], args[myidx]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002980 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002981 goto out;
2982 }
Emeric Brun97679e72010-09-23 17:56:44 +02002983 if (flags & STK_ON_RSP)
2984 err_code |= warnif_cond_requires_req(cond, file, linenum);
2985 else
2986 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002987
Emeric Brunb982a3d2010-01-04 15:45:53 +01002988 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2989 rule->cond = cond;
2990 rule->expr = expr;
2991 rule->flags = flags;
2992 rule->table.name = name ? strdup(name) : NULL;
2993 LIST_INIT(&rule->list);
2994 if (flags & STK_ON_RSP)
2995 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2996 else
2997 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002999 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003000 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003001 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003002
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3004 curproxy->uri_auth = NULL; /* we must detach from the default config */
3005
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003006 if (!*args[1]) {
3007 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003008 } else if (!strcmp(args[1], "admin")) {
3009 struct stats_admin_rule *rule;
3010
3011 if (curproxy == &defproxy) {
3012 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
3015 }
3016
3017 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3018 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3019 err_code |= ERR_ALERT | ERR_ABORT;
3020 goto out;
3021 }
3022
3023 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3024 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3025 file, linenum, args[0], args[1]);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3030 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3031 file, linenum, args[0], args[1]);
3032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
3034 }
3035
3036 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3037
3038 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3039 rule->cond = cond;
3040 LIST_INIT(&rule->list);
3041 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 } else if (!strcmp(args[1], "uri")) {
3043 if (*(args[2]) == 0) {
3044 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3048 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_ALERT | ERR_ABORT;
3050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 }
3052 } else if (!strcmp(args[1], "realm")) {
3053 if (*(args[2]) == 0) {
3054 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3058 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_ABORT;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003062 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003063 unsigned interval;
3064
3065 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3066 if (err) {
3067 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3068 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_ALERT | ERR_FATAL;
3070 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003071 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3072 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_ABORT;
3074 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003075 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003076 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003077 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003078
3079 if (curproxy == &defproxy) {
3080 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084
3085 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3086 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3087 err_code |= ERR_ALERT | ERR_ABORT;
3088 goto out;
3089 }
3090
Willy Tarreauff011f22011-01-06 17:51:27 +01003091 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3092 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003093 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3094 file, linenum, args[0]);
3095 err_code |= ERR_WARN;
3096 }
3097
Willy Tarreauff011f22011-01-06 17:51:27 +01003098 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003099
Willy Tarreauff011f22011-01-06 17:51:27 +01003100 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003101 err_code |= ERR_ALERT | ERR_ABORT;
3102 goto out;
3103 }
3104
Willy Tarreauff011f22011-01-06 17:51:27 +01003105 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3106 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003107
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 } else if (!strcmp(args[1], "auth")) {
3109 if (*(args[2]) == 0) {
3110 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_ALERT | ERR_FATAL;
3112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003115 err_code |= ERR_ALERT | ERR_ABORT;
3116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
3118 } else if (!strcmp(args[1], "scope")) {
3119 if (*(args[2]) == 0) {
3120 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3124 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_ABORT;
3126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 }
3128 } else if (!strcmp(args[1], "enable")) {
3129 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3130 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_ABORT;
3132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003134 } else if (!strcmp(args[1], "hide-version")) {
3135 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3136 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003137 err_code |= ERR_ALERT | ERR_ABORT;
3138 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003139 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003140 } else if (!strcmp(args[1], "show-legends")) {
3141 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3142 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
3145 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003146 } else if (!strcmp(args[1], "show-node")) {
3147
3148 if (*args[2]) {
3149 int i;
3150 char c;
3151
3152 for (i=0; args[2][i]; i++) {
3153 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003154 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3155 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003156 break;
3157 }
3158
3159 if (!i || args[2][i]) {
3160 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3161 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3162 file, linenum, args[0], args[1]);
3163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
3165 }
3166 }
3167
3168 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3169 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3170 err_code |= ERR_ALERT | ERR_ABORT;
3171 goto out;
3172 }
3173 } else if (!strcmp(args[1], "show-desc")) {
3174 char *desc = NULL;
3175
3176 if (*args[2]) {
3177 int i, len=0;
3178 char *d;
3179
3180 for(i=2; *args[i]; i++)
3181 len += strlen(args[i])+1;
3182
3183 desc = d = (char *)calloc(1, len);
3184
3185 d += sprintf(d, "%s", args[2]);
3186 for(i=3; *args[i]; i++)
3187 d += sprintf(d, " %s", args[i]);
3188 }
3189
3190 if (!*args[2] && !global.desc)
3191 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3192 file, linenum, args[1]);
3193 else {
3194 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3195 free(desc);
3196 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3197 err_code |= ERR_ALERT | ERR_ABORT;
3198 goto out;
3199 }
3200 free(desc);
3201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003203stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003204 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 +01003205 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
3209 }
3210 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003211 int optnum;
3212
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003213 if (*(args[1]) == '\0') {
3214 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3215 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003219
3220 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3221 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003222 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3223 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3224 file, linenum, cfg_opts[optnum].name);
3225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
3227 }
Willy Tarreau93893792009-07-23 13:19:11 +02003228 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3229 err_code |= ERR_WARN;
3230 goto out;
3231 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003232
Willy Tarreau3842f002009-06-14 11:39:52 +02003233 curproxy->no_options &= ~cfg_opts[optnum].val;
3234 curproxy->options &= ~cfg_opts[optnum].val;
3235
3236 switch (kwm) {
3237 case KWM_STD:
3238 curproxy->options |= cfg_opts[optnum].val;
3239 break;
3240 case KWM_NO:
3241 curproxy->no_options |= cfg_opts[optnum].val;
3242 break;
3243 case KWM_DEF: /* already cleared */
3244 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003245 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003246
Willy Tarreau93893792009-07-23 13:19:11 +02003247 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003248 }
3249 }
3250
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003251 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3252 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003253 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3254 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3255 file, linenum, cfg_opts2[optnum].name);
3256 err_code |= ERR_ALERT | ERR_FATAL;
3257 goto out;
3258 }
Willy Tarreau93893792009-07-23 13:19:11 +02003259 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3260 err_code |= ERR_WARN;
3261 goto out;
3262 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003263
Willy Tarreau3842f002009-06-14 11:39:52 +02003264 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3265 curproxy->options2 &= ~cfg_opts2[optnum].val;
3266
3267 switch (kwm) {
3268 case KWM_STD:
3269 curproxy->options2 |= cfg_opts2[optnum].val;
3270 break;
3271 case KWM_NO:
3272 curproxy->no_options2 |= cfg_opts2[optnum].val;
3273 break;
3274 case KWM_DEF: /* already cleared */
3275 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003276 }
Willy Tarreau93893792009-07-23 13:19:11 +02003277 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003278 }
3279 }
3280
Willy Tarreau3842f002009-06-14 11:39:52 +02003281 if (kwm != KWM_STD) {
3282 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003283 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003286 }
3287
Emeric Brun3a058f32009-06-30 18:26:00 +02003288 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003290 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003292 if (*(args[2]) != '\0') {
3293 if (!strcmp(args[2], "clf")) {
3294 curproxy->options2 |= PR_O2_CLFLOG;
3295 } else {
3296 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003299 }
3300 }
3301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 else if (!strcmp(args[1], "tcplog"))
3303 /* generate a detailed TCP log */
3304 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 else if (!strcmp(args[1], "tcpka")) {
3306 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003307 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003308 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003309
3310 if (curproxy->cap & PR_CAP_FE)
3311 curproxy->options |= PR_O_TCP_CLI_KA;
3312 if (curproxy->cap & PR_CAP_BE)
3313 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 }
3315 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003316 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003317 err_code |= ERR_WARN;
3318
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003320 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003321 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003322 curproxy->options2 &= ~PR_O2_CHK_ANY;
3323 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 if (!*args[2]) { /* no argument */
3325 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3326 curproxy->check_len = strlen(DEF_CHECK_REQ);
3327 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003328 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003329 curproxy->check_req = (char *)malloc(reqlen);
3330 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003331 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003333 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 if (*args[4])
3335 reqlen += strlen(args[4]);
3336 else
3337 reqlen += strlen("HTTP/1.0");
3338
3339 curproxy->check_req = (char *)malloc(reqlen);
3340 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003341 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003343 }
3344 else if (!strcmp(args[1], "ssl-hello-chk")) {
3345 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003346 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003348
Willy Tarreaua534fea2008-08-03 12:19:50 +02003349 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003350 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003351 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003352 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
Willy Tarreau23677902007-05-08 23:50:35 +02003354 else if (!strcmp(args[1], "smtpchk")) {
3355 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003356 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003357 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003358 curproxy->options2 &= ~PR_O2_CHK_ANY;
3359 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003360
3361 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3362 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3363 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3364 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3365 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3366 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3367 curproxy->check_req = (char *)malloc(reqlen);
3368 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3369 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3370 } else {
3371 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3372 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3373 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3374 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3375 }
3376 }
3377 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003378 else if (!strcmp(args[1], "pgsql-check")) {
3379 /* use PostgreSQL request to check servers' health */
3380 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3381 err_code |= ERR_WARN;
3382
3383 free(curproxy->check_req);
3384 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003385 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003386 curproxy->options2 |= PR_O2_PGSQL_CHK;
3387
3388 if (*(args[2])) {
3389 int cur_arg = 2;
3390
3391 while (*(args[cur_arg])) {
3392 if (strcmp(args[cur_arg], "user") == 0) {
3393 char * packet;
3394 uint32_t packet_len;
3395 uint32_t pv;
3396
3397 /* suboption header - needs additional argument for it */
3398 if (*(args[cur_arg+1]) == 0) {
3399 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3400 file, linenum, args[0], args[1], args[cur_arg]);
3401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
3403 }
3404
3405 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3406 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3407 pv = htonl(0x30000); /* protocol version 3.0 */
3408
3409 packet = (char*) calloc(1, packet_len);
3410
3411 memcpy(packet + 4, &pv, 4);
3412
3413 /* copy "user" */
3414 memcpy(packet + 8, "user", 4);
3415
3416 /* copy username */
3417 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3418
3419 free(curproxy->check_req);
3420 curproxy->check_req = packet;
3421 curproxy->check_len = packet_len;
3422
3423 packet_len = htonl(packet_len);
3424 memcpy(packet, &packet_len, 4);
3425 cur_arg += 2;
3426 } else {
3427 /* unknown suboption - catchall */
3428 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3429 file, linenum, args[0], args[1]);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
3433 } /* end while loop */
3434 }
3435 }
3436
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003437 else if (!strcmp(args[1], "redis-check")) {
3438 /* use REDIS PING request to check servers' health */
3439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3440 err_code |= ERR_WARN;
3441
3442 free(curproxy->check_req);
3443 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003444 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003445 curproxy->options2 |= PR_O2_REDIS_CHK;
3446
3447 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3448 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3449 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3450 }
3451
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003452 else if (!strcmp(args[1], "mysql-check")) {
3453 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003454 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3455 err_code |= ERR_WARN;
3456
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003457 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003458 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003459 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003460 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003461
3462 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3463 * const char mysql40_client_auth_pkt[] = {
3464 * "\x0e\x00\x00" // packet length
3465 * "\x01" // packet number
3466 * "\x00\x00" // client capabilities
3467 * "\x00\x00\x01" // max packet
3468 * "haproxy\x00" // username (null terminated string)
3469 * "\x00" // filler (always 0x00)
3470 * "\x01\x00\x00" // packet length
3471 * "\x00" // packet number
3472 * "\x01" // COM_QUIT command
3473 * };
3474 */
3475
3476 if (*(args[2])) {
3477 int cur_arg = 2;
3478
3479 while (*(args[cur_arg])) {
3480 if (strcmp(args[cur_arg], "user") == 0) {
3481 char *mysqluser;
3482 int packetlen, reqlen, userlen;
3483
3484 /* suboption header - needs additional argument for it */
3485 if (*(args[cur_arg+1]) == 0) {
3486 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3487 file, linenum, args[0], args[1], args[cur_arg]);
3488 err_code |= ERR_ALERT | ERR_FATAL;
3489 goto out;
3490 }
3491 mysqluser = args[cur_arg + 1];
3492 userlen = strlen(mysqluser);
3493 packetlen = userlen + 7;
3494 reqlen = packetlen + 9;
3495
3496 free(curproxy->check_req);
3497 curproxy->check_req = (char *)calloc(1, reqlen);
3498 curproxy->check_len = reqlen;
3499
3500 snprintf(curproxy->check_req, 4, "%c%c%c",
3501 ((unsigned char) packetlen & 0xff),
3502 ((unsigned char) (packetlen >> 8) & 0xff),
3503 ((unsigned char) (packetlen >> 16) & 0xff));
3504
3505 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003506 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003507 curproxy->check_req[8] = 1;
3508 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3509 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3510 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3511 cur_arg += 2;
3512 } else {
3513 /* unknown suboption - catchall */
3514 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3515 file, linenum, args[0], args[1]);
3516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
3518 }
3519 } /* end while loop */
3520 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003521 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003522 else if (!strcmp(args[1], "ldap-check")) {
3523 /* use LDAP request to check servers' health */
3524 free(curproxy->check_req);
3525 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003526 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003527 curproxy->options2 |= PR_O2_LDAP_CHK;
3528
3529 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3530 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3531 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3532 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003533 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003534 int cur_arg;
3535
3536 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3537 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003538 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003539
Willy Tarreau87cf5142011-08-19 22:57:24 +02003540 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003541
3542 free(curproxy->fwdfor_hdr_name);
3543 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3544 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3545
3546 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3547 cur_arg = 2;
3548 while (*(args[cur_arg])) {
3549 if (!strcmp(args[cur_arg], "except")) {
3550 /* suboption except - needs additional argument for it */
3551 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3552 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3553 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003556 }
3557 /* flush useless bits */
3558 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003559 cur_arg += 2;
3560 } else if (!strcmp(args[cur_arg], "header")) {
3561 /* suboption header - needs additional argument for it */
3562 if (*(args[cur_arg+1]) == 0) {
3563 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3564 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003567 }
3568 free(curproxy->fwdfor_hdr_name);
3569 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3570 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3571 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003572 } else if (!strcmp(args[cur_arg], "if-none")) {
3573 curproxy->options &= ~PR_O_FF_ALWAYS;
3574 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003575 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003576 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003577 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003578 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003581 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003582 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003583 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003584 else if (!strcmp(args[1], "originalto")) {
3585 int cur_arg;
3586
3587 /* insert x-original-to field, but not for the IP address listed as an except.
3588 * set default options (ie: bitfield, header name, etc)
3589 */
3590
3591 curproxy->options |= PR_O_ORGTO;
3592
3593 free(curproxy->orgto_hdr_name);
3594 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3595 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3596
Willy Tarreau87cf5142011-08-19 22:57:24 +02003597 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003598 cur_arg = 2;
3599 while (*(args[cur_arg])) {
3600 if (!strcmp(args[cur_arg], "except")) {
3601 /* suboption except - needs additional argument for it */
3602 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3603 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3604 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003607 }
3608 /* flush useless bits */
3609 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3610 cur_arg += 2;
3611 } else if (!strcmp(args[cur_arg], "header")) {
3612 /* suboption header - needs additional argument for it */
3613 if (*(args[cur_arg+1]) == 0) {
3614 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3615 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003618 }
3619 free(curproxy->orgto_hdr_name);
3620 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3621 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3622 cur_arg += 2;
3623 } else {
3624 /* unknown suboption - catchall */
3625 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3626 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003629 }
3630 } /* end while loop */
3631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 else {
3633 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 }
Willy Tarreau93893792009-07-23 13:19:11 +02003637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003638 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003639 else if (!strcmp(args[0], "default_backend")) {
3640 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003642
3643 if (*(args[1]) == 0) {
3644 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003647 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003648 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003649 curproxy->defbe.name = strdup(args[1]);
3650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003652 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003653 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003654
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003655 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3656 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003657 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 /* enable reconnections to dispatch */
3659 curproxy->options |= PR_O_REDISP;
3660 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003661 else if (!strcmp(args[0], "http-check")) {
3662 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003664
3665 if (strcmp(args[1], "disable-on-404") == 0) {
3666 /* enable a graceful server shutdown on an HTTP 404 response */
3667 curproxy->options |= PR_O_DISABLE404;
3668 }
Willy Tarreauef781042010-01-27 11:53:01 +01003669 else if (strcmp(args[1], "send-state") == 0) {
3670 /* enable emission of the apparent state of a server in HTTP checks */
3671 curproxy->options2 |= PR_O2_CHK_SNDST;
3672 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003673 else if (strcmp(args[1], "expect") == 0) {
3674 const char *ptr_arg;
3675 int cur_arg;
3676
3677 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3678 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
3681 }
3682
3683 cur_arg = 2;
3684 /* consider exclamation marks, sole or at the beginning of a word */
3685 while (*(ptr_arg = args[cur_arg])) {
3686 while (*ptr_arg == '!') {
3687 curproxy->options2 ^= PR_O2_EXP_INV;
3688 ptr_arg++;
3689 }
3690 if (*ptr_arg)
3691 break;
3692 cur_arg++;
3693 }
3694 /* now ptr_arg points to the beginning of a word past any possible
3695 * exclamation mark, and cur_arg is the argument which holds this word.
3696 */
3697 if (strcmp(ptr_arg, "status") == 0) {
3698 if (!*(args[cur_arg + 1])) {
3699 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3700 file, linenum, args[0], args[1], ptr_arg);
3701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
3703 }
3704 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003705 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003706 curproxy->expect_str = strdup(args[cur_arg + 1]);
3707 }
3708 else if (strcmp(ptr_arg, "string") == 0) {
3709 if (!*(args[cur_arg + 1])) {
3710 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3711 file, linenum, args[0], args[1], ptr_arg);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003716 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003717 curproxy->expect_str = strdup(args[cur_arg + 1]);
3718 }
3719 else if (strcmp(ptr_arg, "rstatus") == 0) {
3720 if (!*(args[cur_arg + 1])) {
3721 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3722 file, linenum, args[0], args[1], ptr_arg);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003727 free(curproxy->expect_str);
3728 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3729 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003730 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3731 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3732 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3733 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
3736 }
3737 }
3738 else if (strcmp(ptr_arg, "rstring") == 0) {
3739 if (!*(args[cur_arg + 1])) {
3740 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3741 file, linenum, args[0], args[1], ptr_arg);
3742 err_code |= ERR_ALERT | ERR_FATAL;
3743 goto out;
3744 }
3745 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003746 free(curproxy->expect_str);
3747 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3748 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003749 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3750 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3751 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3752 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
3756 }
3757 else {
3758 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3759 file, linenum, args[0], args[1], ptr_arg);
3760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
3762 }
3763 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003764 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003765 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 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003768 }
3769 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003770 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003771 if (curproxy == &defproxy) {
3772 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003775 }
3776
Willy Tarreaub80c2302007-11-30 20:51:32 +01003777 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003779
3780 if (strcmp(args[1], "fail") == 0) {
3781 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003782 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003783 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3784 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003787 }
3788
Willy Tarreauef6494c2010-01-28 17:12:36 +01003789 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003790 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3791 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_ALERT | ERR_FATAL;
3793 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003794 }
3795 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3796 }
3797 else {
3798 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003801 }
3802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003803#ifdef TPROXY
3804 else if (!strcmp(args[0], "transparent")) {
3805 /* enable transparent proxy connections */
3806 curproxy->options |= PR_O_TRANSP;
3807 }
3808#endif
3809 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003810 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003811 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003812
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 if (*(args[1]) == 0) {
3814 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003815 err_code |= ERR_ALERT | ERR_FATAL;
3816 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 }
3818 curproxy->maxconn = atol(args[1]);
3819 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003820 else if (!strcmp(args[0], "backlog")) { /* backlog */
3821 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003823
3824 if (*(args[1]) == 0) {
3825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_ALERT | ERR_FATAL;
3827 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003828 }
3829 curproxy->backlog = atol(args[1]);
3830 }
Willy Tarreau86034312006-12-29 00:10:33 +01003831 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003832 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003834
Willy Tarreau86034312006-12-29 00:10:33 +01003835 if (*(args[1]) == 0) {
3836 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003837 err_code |= ERR_ALERT | ERR_FATAL;
3838 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003839 }
3840 curproxy->fullconn = atol(args[1]);
3841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3843 if (*(args[1]) == 0) {
3844 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003848 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3849 if (err) {
3850 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3851 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003854 }
3855 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 }
3857 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003858 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 if (curproxy == &defproxy) {
3860 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003864 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003866
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 if (strchr(args[1], ':') == NULL) {
3868 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003869 err_code |= ERR_ALERT | ERR_FATAL;
3870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003872 sk = str2sa(args[1]);
3873 if (!sk) {
3874 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3875 err_code |= ERR_ALERT | ERR_FATAL;
3876 goto out;
3877 }
3878 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003879 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
3881 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003882 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003884
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003885 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003886 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3887 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003888 err_code |= ERR_ALERT | ERR_FATAL;
3889 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003892 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3893 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3894 err_code |= ERR_WARN;
3895
3896 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3897 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3898 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3899 }
3900 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3901 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3902 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3903 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003904 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3905 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3906 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3907 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003908 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003909 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003910 err_code |= ERR_ALERT | ERR_FATAL;
3911 goto out;
3912 }
3913 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003914 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003916 char *rport, *raddr;
3917 short realport = 0;
3918 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003920 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003921 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003925 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003926 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927
3928 if (!*args[2]) {
3929 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3930 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003934
3935 err = invalid_char(args[1]);
3936 if (err) {
3937 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3938 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003941 }
3942
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003943 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003944 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003945
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003946 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3947 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3948 err_code |= ERR_ALERT | ERR_ABORT;
3949 goto out;
3950 }
3951
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003952 /* the servers are linked backwards first */
3953 newsrv->next = curproxy->srv;
3954 curproxy->srv = newsrv;
3955 newsrv->proxy = curproxy;
3956 newsrv->conf.file = file;
3957 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003958
Simon Hormanaf514952011-06-21 14:34:57 +09003959 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003960 LIST_INIT(&newsrv->pendconns);
3961 do_check = 0;
3962 newsrv->state = SRV_RUNNING; /* early server setup */
3963 newsrv->last_change = now.tv_sec;
3964 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003966 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003967 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003968 * - IP: => port=+0, relative
3969 * - IP:N => port=N, absolute
3970 * - IP:+N => port=+N, relative
3971 * - IP:-N => port=-N, relative
3972 */
3973 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003974 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003975 if (rport) {
3976 *rport++ = 0;
3977 realport = atol(rport);
3978 if (!isdigit((unsigned char)*rport))
3979 newsrv->state |= SRV_MAPPORTS;
3980 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003981 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003982
Willy Tarreaufab5a432011-03-04 15:31:53 +01003983 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003985 if (!sk) {
3986 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
3990 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003991 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003992
3993 newsrv->check_port = curproxy->defsrv.check_port;
3994 newsrv->inter = curproxy->defsrv.inter;
3995 newsrv->fastinter = curproxy->defsrv.fastinter;
3996 newsrv->downinter = curproxy->defsrv.downinter;
3997 newsrv->rise = curproxy->defsrv.rise;
3998 newsrv->fall = curproxy->defsrv.fall;
3999 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4000 newsrv->minconn = curproxy->defsrv.minconn;
4001 newsrv->maxconn = curproxy->defsrv.maxconn;
4002 newsrv->slowstart = curproxy->defsrv.slowstart;
4003 newsrv->onerror = curproxy->defsrv.onerror;
4004 newsrv->consecutive_errors_limit
4005 = curproxy->defsrv.consecutive_errors_limit;
4006 newsrv->uweight = newsrv->iweight
4007 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004008
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004009 newsrv->curfd = -1; /* no health-check in progress */
4010 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004012 cur_arg = 3;
4013 } else {
4014 newsrv = &curproxy->defsrv;
4015 cur_arg = 1;
4016 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004017
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004019 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004020 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004021
4022 if (!*args[cur_arg + 1]) {
4023 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4024 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004027 }
4028
4029 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004030 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004031
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004032 if (newsrv->puid <= 0) {
4033 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004034 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004037 }
4038
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004039 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4040 if (node) {
4041 struct server *target = container_of(node, struct server, conf.id);
4042 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4043 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
4046 }
4047 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004048 cur_arg += 2;
4049 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004051 newsrv->cookie = strdup(args[cur_arg + 1]);
4052 newsrv->cklen = strlen(args[cur_arg + 1]);
4053 cur_arg += 2;
4054 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004055 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004056 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4057 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4058 cur_arg += 2;
4059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004060 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004061 if (!*args[cur_arg + 1]) {
4062 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4063 file, linenum, args[cur_arg]);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
4066 }
4067
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004069 if (newsrv->rise <= 0) {
4070 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4071 file, linenum, args[cur_arg]);
4072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
4074 }
4075
Willy Tarreau96839092010-03-29 10:02:24 +02004076 if (newsrv->health)
4077 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 cur_arg += 2;
4079 }
4080 else if (!strcmp(args[cur_arg], "fall")) {
4081 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004082
4083 if (!*args[cur_arg + 1]) {
4084 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4085 file, linenum, args[cur_arg]);
4086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
4088 }
4089
4090 if (newsrv->fall <= 0) {
4091 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4092 file, linenum, args[cur_arg]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096
Willy Tarreaubaaee002006-06-26 02:48:02 +02004097 cur_arg += 2;
4098 }
4099 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004100 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4101 if (err) {
4102 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4103 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004106 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004107 if (val <= 0) {
4108 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4109 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004112 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004113 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 cur_arg += 2;
4115 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004116 else if (!strcmp(args[cur_arg], "fastinter")) {
4117 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4118 if (err) {
4119 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4120 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004123 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004124 if (val <= 0) {
4125 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4126 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004129 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004130 newsrv->fastinter = val;
4131 cur_arg += 2;
4132 }
4133 else if (!strcmp(args[cur_arg], "downinter")) {
4134 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4135 if (err) {
4136 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4137 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004138 err_code |= ERR_ALERT | ERR_FATAL;
4139 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004140 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004141 if (val <= 0) {
4142 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4143 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004146 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004147 newsrv->downinter = val;
4148 cur_arg += 2;
4149 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004150 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004151 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004152 if (!sk) {
4153 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
4156 }
4157 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004158 cur_arg += 2;
4159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004160 else if (!strcmp(args[cur_arg], "port")) {
4161 newsrv->check_port = atol(args[cur_arg + 1]);
4162 cur_arg += 2;
4163 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004164 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 newsrv->state |= SRV_BACKUP;
4166 cur_arg ++;
4167 }
Simon Hormanfa461682011-06-25 09:39:49 +09004168 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4169 newsrv->state |= SRV_NON_STICK;
4170 cur_arg ++;
4171 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004172 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4173 newsrv->state |= SRV_SEND_PROXY;
4174 cur_arg ++;
4175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004176 else if (!strcmp(args[cur_arg], "weight")) {
4177 int w;
4178 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004179 if (w < 0 || w > 256) {
4180 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004181 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004184 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004185 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 cur_arg += 2;
4187 }
4188 else if (!strcmp(args[cur_arg], "minconn")) {
4189 newsrv->minconn = atol(args[cur_arg + 1]);
4190 cur_arg += 2;
4191 }
4192 else if (!strcmp(args[cur_arg], "maxconn")) {
4193 newsrv->maxconn = atol(args[cur_arg + 1]);
4194 cur_arg += 2;
4195 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004196 else if (!strcmp(args[cur_arg], "maxqueue")) {
4197 newsrv->maxqueue = atol(args[cur_arg + 1]);
4198 cur_arg += 2;
4199 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004200 else if (!strcmp(args[cur_arg], "slowstart")) {
4201 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004202 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004203 if (err) {
4204 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4205 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004208 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004209 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004210 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4211 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004214 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004215 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004216 cur_arg += 2;
4217 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004218 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004219
4220 if (!*args[cur_arg + 1]) {
4221 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4222 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004225 }
4226
4227 newsrv->trackit = strdup(args[cur_arg + 1]);
4228
4229 cur_arg += 2;
4230 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004231 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004232 global.maxsock++;
4233 do_check = 1;
4234 cur_arg += 1;
4235 }
Willy Tarreau96839092010-03-29 10:02:24 +02004236 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4237 newsrv->state |= SRV_MAINTAIN;
4238 newsrv->state &= ~SRV_RUNNING;
4239 newsrv->health = 0;
4240 cur_arg += 1;
4241 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004242 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004243 if (!strcmp(args[cur_arg + 1], "none"))
4244 newsrv->observe = HANA_OBS_NONE;
4245 else if (!strcmp(args[cur_arg + 1], "layer4"))
4246 newsrv->observe = HANA_OBS_LAYER4;
4247 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4248 if (curproxy->mode != PR_MODE_HTTP) {
4249 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4250 file, linenum, args[cur_arg + 1]);
4251 err_code |= ERR_ALERT;
4252 }
4253 newsrv->observe = HANA_OBS_LAYER7;
4254 }
4255 else {
4256 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004257 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004258 file, linenum, args[cur_arg], args[cur_arg + 1]);
4259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
4262
4263 cur_arg += 2;
4264 }
4265 else if (!strcmp(args[cur_arg], "on-error")) {
4266 if (!strcmp(args[cur_arg + 1], "fastinter"))
4267 newsrv->onerror = HANA_ONERR_FASTINTER;
4268 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4269 newsrv->onerror = HANA_ONERR_FAILCHK;
4270 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4271 newsrv->onerror = HANA_ONERR_SUDDTH;
4272 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4273 newsrv->onerror = HANA_ONERR_MARKDWN;
4274 else {
4275 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004276 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004277 file, linenum, args[cur_arg], args[cur_arg + 1]);
4278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
4280 }
4281
4282 cur_arg += 2;
4283 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004284 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4285 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4286 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4287 else {
4288 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4289 file, linenum, args[cur_arg], args[cur_arg + 1]);
4290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
4292 }
4293
4294 cur_arg += 2;
4295 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004296 else if (!strcmp(args[cur_arg], "error-limit")) {
4297 if (!*args[cur_arg + 1]) {
4298 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4299 file, linenum, args[cur_arg]);
4300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
4302 }
4303
4304 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4305
4306 if (newsrv->consecutive_errors_limit <= 0) {
4307 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4308 file, linenum, args[cur_arg]);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004312 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004313 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004314 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004315 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004316 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004317
Willy Tarreaubaaee002006-06-26 02:48:02 +02004318 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004319#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004320 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004321 file, linenum, "source", "usesrc");
4322#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004323 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004324 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004325#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 }
4329 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004330 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4331 if (!sk) {
4332 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
4335 }
4336 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004337
4338 if (port_low != port_high) {
4339 int i;
4340 if (port_low <= 0 || port_low > 65535 ||
4341 port_high <= 0 || port_high > 65535 ||
4342 port_low > port_high) {
4343 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4344 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004345 err_code |= ERR_ALERT | ERR_FATAL;
4346 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004347 }
4348 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4349 for (i = 0; i < newsrv->sport_range->size; i++)
4350 newsrv->sport_range->ports[i] = port_low + i;
4351 }
4352
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004354 while (*(args[cur_arg])) {
4355 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004356#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4357#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004358 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4359 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4360 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004363 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004364#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004365 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004366 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004367 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004370 }
4371 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004372 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004373 newsrv->state |= SRV_TPROXY_CLI;
4374 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004375 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004376 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004377 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4378 char *name, *end;
4379
4380 name = args[cur_arg+1] + 7;
4381 while (isspace(*name))
4382 name++;
4383
4384 end = name;
4385 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4386 end++;
4387
4388 newsrv->state &= ~SRV_TPROXY_MASK;
4389 newsrv->state |= SRV_TPROXY_DYN;
4390 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4391 newsrv->bind_hdr_len = end - name;
4392 memcpy(newsrv->bind_hdr_name, name, end - name);
4393 newsrv->bind_hdr_name[end-name] = '\0';
4394 newsrv->bind_hdr_occ = -1;
4395
4396 /* now look for an occurrence number */
4397 while (isspace(*end))
4398 end++;
4399 if (*end == ',') {
4400 end++;
4401 name = end;
4402 if (*end == '-')
4403 end++;
4404 while (isdigit(*end))
4405 end++;
4406 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4407 }
4408
4409 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4410 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4411 " occurrences values smaller than %d.\n",
4412 file, linenum, MAX_HDR_HISTORY);
4413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
4415 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004416 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004417 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004418 if (!sk) {
4419 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004424 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004425 }
4426 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004427#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004428 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004429#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004430 cur_arg += 2;
4431 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004432#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004433 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004434 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004437#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4438 } /* "usesrc" */
4439
4440 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4441#ifdef SO_BINDTODEVICE
4442 if (!*args[cur_arg + 1]) {
4443 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004447 }
4448 if (newsrv->iface_name)
4449 free(newsrv->iface_name);
4450
4451 newsrv->iface_name = strdup(args[cur_arg + 1]);
4452 newsrv->iface_len = strlen(newsrv->iface_name);
4453 global.last_checks |= LSTCHK_NETADM;
4454#else
4455 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4456 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004457 err_code |= ERR_ALERT | ERR_FATAL;
4458 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004459#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004460 cur_arg += 2;
4461 continue;
4462 }
4463 /* this keyword in not an option of "source" */
4464 break;
4465 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004466 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004467 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004468 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4469 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004470 err_code |= ERR_ALERT | ERR_FATAL;
4471 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004473 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004474 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004475 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 +01004476 file, linenum, newsrv->id);
4477 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004478 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 +01004479 file, linenum);
4480
Willy Tarreau93893792009-07-23 13:19:11 +02004481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004483 }
4484 }
4485
4486 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004487 if (newsrv->trackit) {
4488 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4489 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004490 err_code |= ERR_ALERT | ERR_FATAL;
4491 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004492 }
4493
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004494 /* try to get the port from check_addr if check_port not set */
4495 if (!newsrv->check_port)
4496 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004497
Willy Tarreaubaaee002006-06-26 02:48:02 +02004498 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4499 newsrv->check_port = realport; /* by default */
4500 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004501 /* not yet valid, because no port was set on
4502 * the server either. We'll check if we have
4503 * a known port on the first listener.
4504 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004505 struct listener *l = curproxy->listen;
4506 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4507 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004508 }
4509 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4511 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_ALERT | ERR_FATAL;
4513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004515
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004516 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004517 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004518 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4519 err_code |= ERR_ALERT | ERR_ABORT;
4520 goto out;
4521 }
4522
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004523 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524 newsrv->state |= SRV_CHECKED;
4525 }
4526
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004527 if (!defsrv) {
4528 if (newsrv->state & SRV_BACKUP)
4529 curproxy->srv_bck++;
4530 else
4531 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004532
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004533 newsrv->prev_state = newsrv->state;
4534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 }
William Lallemand0f99e342011-10-12 17:50:54 +02004536 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4537 /* delete previous herited or defined syslog servers */
4538 struct logsrv *back;
4539
4540 if (*(args[1]) != 0) {
4541 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
4545
4546 list_for_each_entry_safe(tmp, back, &curproxy->logsrvs, list) {
4547 LIST_DEL(&tmp->list);
4548 free(tmp);
4549 }
4550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004552 struct logsrv *logsrv;
4553
Willy Tarreaubaaee002006-06-26 02:48:02 +02004554 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004555 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
4556 list_for_each_entry(tmp, &global.logsrvs, list) {
4557 struct logsrv *node = malloc(sizeof(struct logsrv));
4558 memcpy(node, tmp, sizeof(struct logsrv));
4559 LIST_INIT(&node->list);
4560 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004562 }
4563 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004564
4565 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004566
William Lallemand0f99e342011-10-12 17:50:54 +02004567 logsrv->facility = get_log_facility(args[2]);
4568 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
4572
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
4574
William Lallemand0f99e342011-10-12 17:50:54 +02004575 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004577 logsrv->level = get_log_level(args[3]);
4578 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
4582
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
4584 }
4585
William Lallemand0f99e342011-10-12 17:50:54 +02004586 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004587 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004588 logsrv->minlvl = get_log_level(args[4]);
4589 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004590 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
4593
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004594 }
4595 }
4596
Robert Tsai81ae1952007-12-05 10:47:29 +01004597 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004598 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004599 if (!sk) {
4600 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004601 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604 }
William Lallemand0f99e342011-10-12 17:50:54 +02004605 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004606 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004607 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004608 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004609 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
William Lallemand0f99e342011-10-12 17:50:54 +02004613 logsrv->addr = *sk;
4614 if (!get_host_port(&logsrv->addr))
4615 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004616 }
William Lallemand0f99e342011-10-12 17:50:54 +02004617
4618 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
4620 else {
4621 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4622 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004623 err_code |= ERR_ALERT | ERR_FATAL;
4624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625 }
4626 }
4627 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004628 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004629 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004630
Willy Tarreau977b8e42006-12-29 14:19:17 +01004631 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004632 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004633
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004635 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4636 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004640
4641 /* we must first clear any optional default setting */
4642 curproxy->options &= ~PR_O_TPXY_MASK;
4643 free(curproxy->iface_name);
4644 curproxy->iface_name = NULL;
4645 curproxy->iface_len = 0;
4646
Willy Tarreaud5191e72010-02-09 20:50:45 +01004647 sk = str2sa(args[1]);
4648 if (!sk) {
4649 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
4652 }
4653 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004654 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004655
4656 cur_arg = 2;
4657 while (*(args[cur_arg])) {
4658 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004659#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4660#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004661 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4662 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4663 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004666 }
4667#endif
4668 if (!*args[cur_arg + 1]) {
4669 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4670 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004673 }
4674
4675 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004676 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004677 curproxy->options |= PR_O_TPXY_CLI;
4678 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004679 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004680 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004681 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4682 char *name, *end;
4683
4684 name = args[cur_arg+1] + 7;
4685 while (isspace(*name))
4686 name++;
4687
4688 end = name;
4689 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4690 end++;
4691
4692 curproxy->options &= ~PR_O_TPXY_MASK;
4693 curproxy->options |= PR_O_TPXY_DYN;
4694 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4695 curproxy->bind_hdr_len = end - name;
4696 memcpy(curproxy->bind_hdr_name, name, end - name);
4697 curproxy->bind_hdr_name[end-name] = '\0';
4698 curproxy->bind_hdr_occ = -1;
4699
4700 /* now look for an occurrence number */
4701 while (isspace(*end))
4702 end++;
4703 if (*end == ',') {
4704 end++;
4705 name = end;
4706 if (*end == '-')
4707 end++;
4708 while (isdigit(*end))
4709 end++;
4710 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4711 }
4712
4713 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4714 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4715 " occurrences values smaller than %d.\n",
4716 file, linenum, MAX_HDR_HISTORY);
4717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
4719 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004720 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004721 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004722 if (!sk) {
4723 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
4726 }
4727 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004728 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004729 }
4730 global.last_checks |= LSTCHK_NETADM;
4731#if !defined(CONFIG_HAP_LINUX_TPROXY)
4732 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004733#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004734#else /* no TPROXY support */
4735 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004736 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004739#endif
4740 cur_arg += 2;
4741 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004742 }
4743
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004744 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4745#ifdef SO_BINDTODEVICE
4746 if (!*args[cur_arg + 1]) {
4747 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004749 err_code |= ERR_ALERT | ERR_FATAL;
4750 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004751 }
4752 if (curproxy->iface_name)
4753 free(curproxy->iface_name);
4754
4755 curproxy->iface_name = strdup(args[cur_arg + 1]);
4756 curproxy->iface_len = strlen(curproxy->iface_name);
4757 global.last_checks |= LSTCHK_NETADM;
4758#else
4759 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4760 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004763#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004764 cur_arg += 2;
4765 continue;
4766 }
4767 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4768 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004773 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4774 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4775 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004780 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004781 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4782 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004785 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004786
4787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4788 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004789 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004792 }
4793 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4795 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004796 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 }
4800 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4802 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004803 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 }
4807 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4809 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004810 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 }
4814 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004815 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4816 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004817 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004818 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004819 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004821 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004822 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4823 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004824 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004825 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004826 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004827 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004828 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004829 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4830 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004831 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004832 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004833 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004834 }
4835 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004836 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4837 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004838 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004839 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004840 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004841 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004842 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004843 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004844 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004848 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849
4850 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4851 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004852 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004853 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 }
4856 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004857 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4858 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004859 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004860 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
4863 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004864 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4865 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004866 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004867 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
4870 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004871 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4872 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004873 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004874 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004876 }
4877 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004878 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4879 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004880 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004881 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004883 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004884 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004885 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4886 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004887 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004888 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004889 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004891 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004892 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004893
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 if (curproxy == &defproxy) {
4895 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004899 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 if (*(args[1]) == 0) {
4903 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004907
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004908 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4909 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4910 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4911 file, linenum, args[0]);
4912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
4914 }
4915 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4916 }
4917 else if (*args[2]) {
4918 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4919 file, linenum, args[0], args[2]);
4920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
4922 }
4923
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004924 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004925 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004926 wl->s = strdup(args[1]);
4927 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004928 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
4930 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004931 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004937
Willy Tarreauade5ec42010-01-28 19:33:49 +01004938 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4939 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004940 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004941 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004942 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
4944 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004945 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4946 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004947 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
4951 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004952 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4953 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004954 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004955 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
4958 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004959 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4961 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
4965
Willy Tarreauade5ec42010-01-28 19:33:49 +01004966 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4967 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004968 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004969 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 }
4972 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004973 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4974 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004975 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 }
4979 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004980 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4981 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004982 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 }
4986 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004987 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004988
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 if (curproxy == &defproxy) {
4990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004993 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004994 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004996
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 if (*(args[1]) == 0) {
4998 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005003 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
5004 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5005 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5006 file, linenum, args[0]);
5007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
5009 }
5010 err_code |= warnif_cond_requires_req(cond, file, linenum);
5011 }
5012 else if (*args[2]) {
5013 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5014 file, linenum, args[0], args[2]);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
5018
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005019 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005020 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005021 wl->s = strdup(args[1]);
5022 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
5024 else if (!strcmp(args[0], "errorloc") ||
5025 !strcmp(args[0], "errorloc302") ||
5026 !strcmp(args[0], "errorloc303")) { /* error location */
5027 int errnum, errlen;
5028 char *err;
5029
Willy Tarreau977b8e42006-12-29 14:19:17 +01005030 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005032
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005034 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
5038
5039 errnum = atol(args[1]);
5040 if (!strcmp(args[0], "errorloc303")) {
5041 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5042 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5043 } else {
5044 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5045 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5046 }
5047
Willy Tarreau0f772532006-12-23 20:51:41 +01005048 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5049 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005050 chunk_destroy(&curproxy->errmsg[rc]);
5051 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005052 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005055
5056 if (rc >= HTTP_ERR_SIZE) {
5057 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5058 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 free(err);
5060 }
5061 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005062 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5063 int errnum, errlen, fd;
5064 char *err;
5065 struct stat stat;
5066
5067 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005069
5070 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005071 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005074 }
5075
5076 fd = open(args[2], O_RDONLY);
5077 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5078 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5079 file, linenum, args[2], args[1]);
5080 if (fd >= 0)
5081 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005084 }
5085
Willy Tarreau27a674e2009-08-17 07:23:33 +02005086 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005087 errlen = stat.st_size;
5088 } else {
5089 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005090 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005092 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005093 }
5094
5095 err = malloc(errlen); /* malloc() must succeed during parsing */
5096 errnum = read(fd, err, errlen);
5097 if (errnum != errlen) {
5098 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5099 file, linenum, args[2], args[1]);
5100 close(fd);
5101 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005104 }
5105 close(fd);
5106
5107 errnum = atol(args[1]);
5108 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5109 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005110 chunk_destroy(&curproxy->errmsg[rc]);
5111 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005112 break;
5113 }
5114 }
5115
5116 if (rc >= HTTP_ERR_SIZE) {
5117 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5118 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005119 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005120 free(err);
5121 }
5122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005123 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005124 struct cfg_kw_list *kwl;
5125 int index;
5126
5127 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5128 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5129 if (kwl->kw[index].section != CFG_LISTEN)
5130 continue;
5131 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5132 /* prepare error message just in case */
5133 snprintf(trash, sizeof(trash),
5134 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005135 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5136 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005137 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005140 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005141 else if (rc > 0) {
5142 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_WARN;
5144 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005145 }
Willy Tarreau93893792009-07-23 13:19:11 +02005146 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005147 }
5148 }
5149 }
5150
Willy Tarreau6daf3432008-01-22 16:44:08 +01005151 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 }
Willy Tarreau93893792009-07-23 13:19:11 +02005155 out:
5156 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157}
5158
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005159int
5160cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5161{
5162
5163 int err_code = 0;
5164 const char *err;
5165
5166 if (!strcmp(args[0], "userlist")) { /* new userlist */
5167 struct userlist *newul;
5168
5169 if (!*args[1]) {
5170 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5171 file, linenum, args[0]);
5172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
5174 }
5175
5176 err = invalid_char(args[1]);
5177 if (err) {
5178 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5179 file, linenum, *err, args[0], args[1]);
5180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
5182 }
5183
5184 for (newul = userlist; newul; newul = newul->next)
5185 if (!strcmp(newul->name, args[1])) {
5186 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5187 file, linenum, args[1]);
5188 err_code |= ERR_WARN;
5189 goto out;
5190 }
5191
5192 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5193 if (!newul) {
5194 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5195 err_code |= ERR_ALERT | ERR_ABORT;
5196 goto out;
5197 }
5198
5199 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5200 newul->name = strdup(args[1]);
5201
5202 if (!newul->groupusers | !newul->name) {
5203 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5204 err_code |= ERR_ALERT | ERR_ABORT;
5205 goto out;
5206 }
5207
5208 newul->next = userlist;
5209 userlist = newul;
5210
5211 } else if (!strcmp(args[0], "group")) { /* new group */
5212 int cur_arg, i;
5213 const char *err;
5214
5215 if (!*args[1]) {
5216 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5217 file, linenum, args[0]);
5218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220 }
5221
5222 err = invalid_char(args[1]);
5223 if (err) {
5224 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5225 file, linenum, *err, args[0], args[1]);
5226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
5228 }
5229
5230 for(i = 0; i < userlist->grpcnt; i++)
5231 if (!strcmp(userlist->groups[i], args[1])) {
5232 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5233 file, linenum, args[1], userlist->name);
5234 err_code |= ERR_ALERT;
5235 goto out;
5236 }
5237
5238 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5239 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5240 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
5243 }
5244
5245 cur_arg = 2;
5246
5247 while (*args[cur_arg]) {
5248 if (!strcmp(args[cur_arg], "users")) {
5249 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5250 cur_arg += 2;
5251 continue;
5252 } else {
5253 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5254 file, linenum, args[0]);
5255 err_code |= ERR_ALERT | ERR_FATAL;
5256 goto out;
5257 }
5258 }
5259
5260 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5261 } else if (!strcmp(args[0], "user")) { /* new user */
5262 struct auth_users *newuser;
5263 int cur_arg;
5264
5265 if (!*args[1]) {
5266 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5267 file, linenum, args[0]);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271
5272 for (newuser = userlist->users; newuser; newuser = newuser->next)
5273 if (!strcmp(newuser->user, args[1])) {
5274 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5275 file, linenum, args[1], userlist->name);
5276 err_code |= ERR_ALERT;
5277 goto out;
5278 }
5279
5280 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5281 if (!newuser) {
5282 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5283 err_code |= ERR_ALERT | ERR_ABORT;
5284 goto out;
5285 }
5286
5287 newuser->user = strdup(args[1]);
5288
5289 newuser->next = userlist->users;
5290 userlist->users = newuser;
5291
5292 cur_arg = 2;
5293
5294 while (*args[cur_arg]) {
5295 if (!strcmp(args[cur_arg], "password")) {
5296#ifndef CONFIG_HAP_CRYPT
5297 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5298 file, linenum);
5299 err_code |= ERR_ALERT;
5300#endif
5301 newuser->pass = strdup(args[cur_arg + 1]);
5302 cur_arg += 2;
5303 continue;
5304 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5305 newuser->pass = strdup(args[cur_arg + 1]);
5306 newuser->flags |= AU_O_INSECURE;
5307 cur_arg += 2;
5308 continue;
5309 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005310 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005311 cur_arg += 2;
5312 continue;
5313 } else {
5314 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5315 file, linenum, args[0]);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
5319 }
5320 } else {
5321 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5322 err_code |= ERR_ALERT | ERR_FATAL;
5323 }
5324
5325out:
5326 return err_code;
5327}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328
5329/*
5330 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005331 * Returns the error code, 0 if OK, or any combination of :
5332 * - ERR_ABORT: must abort ASAP
5333 * - ERR_FATAL: we can continue parsing but not start the service
5334 * - ERR_WARN: a warning has been emitted
5335 * - ERR_ALERT: an alert has been emitted
5336 * Only the two first ones can stop processing, the two others are just
5337 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005338 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005339int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005341 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 FILE *f;
5343 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005345 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346
Willy Tarreaubaaee002006-06-26 02:48:02 +02005347 if ((f=fopen(file,"r")) == NULL)
5348 return -1;
5349
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005350 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005351 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005352 char *end;
5353 char *args[MAX_LINE_ARGS + 1];
5354 char *line = thisline;
5355
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 linenum++;
5357
5358 end = line + strlen(line);
5359
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005360 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5361 /* Check if we reached the limit and the last char is not \n.
5362 * Watch out for the last line without the terminating '\n'!
5363 */
5364 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005365 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005366 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005367 }
5368
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005370 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 line++;
5372
5373 arg = 0;
5374 args[arg] = line;
5375
5376 while (*line && arg < MAX_LINE_ARGS) {
5377 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5378 * C equivalent value. Other combinations left unchanged (eg: \1).
5379 */
5380 if (*line == '\\') {
5381 int skip = 0;
5382 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5383 *line = line[1];
5384 skip = 1;
5385 }
5386 else if (line[1] == 'r') {
5387 *line = '\r';
5388 skip = 1;
5389 }
5390 else if (line[1] == 'n') {
5391 *line = '\n';
5392 skip = 1;
5393 }
5394 else if (line[1] == 't') {
5395 *line = '\t';
5396 skip = 1;
5397 }
5398 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005399 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005400 unsigned char hex1, hex2;
5401 hex1 = toupper(line[2]) - '0';
5402 hex2 = toupper(line[3]) - '0';
5403 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5404 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5405 *line = (hex1<<4) + hex2;
5406 skip = 3;
5407 }
5408 else {
5409 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005410 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005411 }
5412 }
5413 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005414 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 end -= skip;
5416 }
5417 line++;
5418 }
5419 else if (*line == '#' || *line == '\n' || *line == '\r') {
5420 /* end of string, end of loop */
5421 *line = 0;
5422 break;
5423 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005424 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005426 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005427 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 line++;
5429 args[++arg] = line;
5430 }
5431 else {
5432 line++;
5433 }
5434 }
5435
5436 /* empty line */
5437 if (!**args)
5438 continue;
5439
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005440 if (*line) {
5441 /* we had to stop due to too many args.
5442 * Let's terminate the string, print the offending part then cut the
5443 * last arg.
5444 */
5445 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5446 line++;
5447 *line = '\0';
5448
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005449 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005450 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 args[arg] = line;
5453 }
5454
Willy Tarreau540abe42007-05-02 20:50:16 +02005455 /* zero out remaining args and ensure that at least one entry
5456 * is zeroed out.
5457 */
5458 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459 args[arg] = line;
5460 }
5461
Willy Tarreau3842f002009-06-14 11:39:52 +02005462 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005463 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005464 char *tmp;
5465
Willy Tarreau3842f002009-06-14 11:39:52 +02005466 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005467 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005468 for (arg=0; *args[arg+1]; arg++)
5469 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005470 *tmp = '\0'; // fix the next arg to \0
5471 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005472 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005473 else if (!strcmp(args[0], "default")) {
5474 kwm = KWM_DEF;
5475 for (arg=0; *args[arg+1]; arg++)
5476 args[arg] = args[arg+1]; // shift args after inversion
5477 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005478
William Lallemand0f99e342011-10-12 17:50:54 +02005479 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5480 strcmp(args[0], "log") != 0) {
5481 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005482 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005483 }
5484
Willy Tarreau977b8e42006-12-29 14:19:17 +01005485 if (!strcmp(args[0], "listen") ||
5486 !strcmp(args[0], "frontend") ||
5487 !strcmp(args[0], "backend") ||
5488 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005489 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005491 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005492 cursection = strdup(args[0]);
5493 }
5494 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005496 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005497 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005498 }
5499 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005500 confsect = CFG_USERLIST;
5501 free(cursection);
5502 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005503 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005504 else if (!strcmp(args[0], "peers")) {
5505 confsect = CFG_PEERS;
5506 free(cursection);
5507 cursection = strdup(args[0]);
5508 }
5509
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 /* else it's a section keyword */
5511
5512 switch (confsect) {
5513 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005514 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515 break;
5516 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005517 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005519 case CFG_USERLIST:
5520 err_code |= cfg_parse_users(file, linenum, args, kwm);
5521 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005522 case CFG_PEERS:
5523 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5524 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005525 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005526 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005527 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005529
5530 if (err_code & ERR_ABORT)
5531 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005533 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005534 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005536 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005537}
5538
Willy Tarreaubb925012009-07-23 13:36:36 +02005539/*
5540 * Returns the error code, 0 if OK, or any combination of :
5541 * - ERR_ABORT: must abort ASAP
5542 * - ERR_FATAL: we can continue parsing but not start the service
5543 * - ERR_WARN: a warning has been emitted
5544 * - ERR_ALERT: an alert has been emitted
5545 * Only the two first ones can stop processing, the two others are just
5546 * indicators.
5547 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005548int check_config_validity()
5549{
5550 int cfgerr = 0;
5551 struct proxy *curproxy = NULL;
5552 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005553 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005554 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005555 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556
5557 /*
5558 * Now, check for the integrity of all that we have collected.
5559 */
5560
5561 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005562 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005564 /* first, we will invert the proxy list order */
5565 curproxy = NULL;
5566 while (proxy) {
5567 struct proxy *next;
5568
5569 next = proxy->next;
5570 proxy->next = curproxy;
5571 curproxy = proxy;
5572 if (!next)
5573 break;
5574 proxy = next;
5575 }
5576
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005578 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005581 }
5582
5583 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005584 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005585 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005586 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005587 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005588 unsigned int next_id;
5589
5590 if (!curproxy->uuid) {
5591 /* proxy ID not set, use automatic numbering with first
5592 * spare entry starting with next_pxid.
5593 */
5594 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5595 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5596 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005597 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005598 next_pxid++;
5599
Willy Tarreau55ea7572007-06-17 19:56:27 +02005600
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005602 /* ensure we don't keep listeners uselessly bound */
5603 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 curproxy = curproxy->next;
5605 continue;
5606 }
5607
Willy Tarreauff01a212009-03-15 13:46:16 +01005608 switch (curproxy->mode) {
5609 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005610 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005611 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005612 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5613 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005614 cfgerr++;
5615 }
5616
5617 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005618 Warning("config : servers will be ignored for %s '%s'.\n",
5619 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005620 break;
5621
5622 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005623 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005624 break;
5625
5626 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005627 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005628 break;
5629 }
5630
5631 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005632 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5633 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 cfgerr++;
5635 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005636
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005637 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005638 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005639 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005640 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5641 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005642 cfgerr++;
5643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005644#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005645 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005646 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5647 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005648 cfgerr++;
5649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005651 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005652 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5653 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005654 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005655 }
5656 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005657 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005658 /* If no LB algo is set in a backend, and we're not in
5659 * transparent mode, dispatch mode nor proxy mode, we
5660 * want to use balance roundrobin by default.
5661 */
5662 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5663 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 }
5665 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005666
Willy Tarreau1620ec32011-08-06 17:05:02 +02005667 if (curproxy->options & PR_O_DISPATCH)
5668 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5669 else if (curproxy->options & PR_O_HTTP_PROXY)
5670 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5671 else if (curproxy->options & PR_O_TRANSP)
5672 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005673
Willy Tarreau1620ec32011-08-06 17:05:02 +02005674 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5675 if (curproxy->options & PR_O_DISABLE404) {
5676 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5677 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5678 err_code |= ERR_WARN;
5679 curproxy->options &= ~PR_O_DISABLE404;
5680 }
5681 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5682 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5683 "send-state", proxy_type_str(curproxy), curproxy->id);
5684 err_code |= ERR_WARN;
5685 curproxy->options &= ~PR_O2_CHK_SNDST;
5686 }
Willy Tarreauef781042010-01-27 11:53:01 +01005687 }
5688
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005689 /* if a default backend was specified, let's find it */
5690 if (curproxy->defbe.name) {
5691 struct proxy *target;
5692
Alex Williams96532db2009-11-01 21:27:13 -05005693 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005694 if (!target) {
5695 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5696 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005697 cfgerr++;
5698 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005699 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5700 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005701 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005702 } else {
5703 free(curproxy->defbe.name);
5704 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005705 /* we force the backend to be present on at least all of
5706 * the frontend's processes.
5707 */
5708 target->bind_proc = curproxy->bind_proc ?
5709 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
5711 }
5712
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005713 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005714 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5715 /* map jump target for ACT_SETBE in req_rep chain */
5716 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005717 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005718 struct proxy *target;
5719
Willy Tarreaua496b602006-12-17 23:15:24 +01005720 if (exp->action != ACT_SETBE)
5721 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005722
Alex Williams96532db2009-11-01 21:27:13 -05005723 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005724 if (!target) {
5725 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5726 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005727 cfgerr++;
5728 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005729 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5730 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005731 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005732 } else {
5733 free((void *)exp->replace);
5734 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005735 /* we force the backend to be present on at least all of
5736 * the frontend's processes.
5737 */
5738 target->bind_proc = curproxy->bind_proc ?
5739 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005740 }
5741 }
5742 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005743
5744 /* find the target proxy for 'use_backend' rules */
5745 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005746 struct proxy *target;
5747
Alex Williams96532db2009-11-01 21:27:13 -05005748 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005749
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005750 if (!target) {
5751 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5752 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005753 cfgerr++;
5754 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005755 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5756 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005757 cfgerr++;
5758 } else {
5759 free((void *)rule->be.name);
5760 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005761 /* we force the backend to be present on at least all of
5762 * the frontend's processes.
5763 */
5764 target->bind_proc = curproxy->bind_proc ?
5765 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005766 }
5767 }
5768
Emeric Brunb982a3d2010-01-04 15:45:53 +01005769 /* find the target table for 'stick' rules */
5770 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5771 struct proxy *target;
5772
Emeric Brun1d33b292010-01-04 15:47:17 +01005773 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5774 if (mrule->flags & STK_IS_STORE)
5775 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5776
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005778 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005779 else
5780 target = curproxy;
5781
5782 if (!target) {
5783 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5784 curproxy->id, mrule->table.name);
5785 cfgerr++;
5786 }
5787 else if (target->table.size == 0) {
5788 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5789 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5790 cfgerr++;
5791 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005792 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005793 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5794 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5795 cfgerr++;
5796 }
5797 else {
5798 free((void *)mrule->table.name);
5799 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005800 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005801 }
5802 }
5803
5804 /* find the target table for 'store response' rules */
5805 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5806 struct proxy *target;
5807
Emeric Brun1d33b292010-01-04 15:47:17 +01005808 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5809
Emeric Brunb982a3d2010-01-04 15:45:53 +01005810 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005811 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005812 else
5813 target = curproxy;
5814
5815 if (!target) {
5816 Alert("Proxy '%s': unable to find store table '%s'.\n",
5817 curproxy->id, mrule->table.name);
5818 cfgerr++;
5819 }
5820 else if (target->table.size == 0) {
5821 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5822 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5823 cfgerr++;
5824 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005825 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005826 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5827 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5828 cfgerr++;
5829 }
5830 else {
5831 free((void *)mrule->table.name);
5832 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005833 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005834 }
5835 }
5836
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005837 /* find the target table for 'tcp-request' layer 4 rules */
5838 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5839 struct proxy *target;
5840
Willy Tarreau56123282010-08-06 19:06:56 +02005841 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005842 continue;
5843
5844 if (trule->act_prm.trk_ctr.table.n)
5845 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5846 else
5847 target = curproxy;
5848
5849 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005850 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5851 curproxy->id, trule->act_prm.trk_ctr.table.n,
5852 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005853 cfgerr++;
5854 }
5855 else if (target->table.size == 0) {
5856 Alert("Proxy '%s': table '%s' used but not configured.\n",
5857 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5858 cfgerr++;
5859 }
5860 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005861 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 +02005862 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5863 cfgerr++;
5864 }
5865 else {
5866 free(trule->act_prm.trk_ctr.table.n);
5867 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005868 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005869 * to pass a list of counters to track and allocate them right here using
5870 * stktable_alloc_data_type().
5871 */
5872 }
5873 }
5874
Willy Tarreaud1f96522010-08-03 19:34:32 +02005875 /* find the target table for 'tcp-request' layer 6 rules */
5876 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5877 struct proxy *target;
5878
Willy Tarreau56123282010-08-06 19:06:56 +02005879 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005880 continue;
5881
5882 if (trule->act_prm.trk_ctr.table.n)
5883 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5884 else
5885 target = curproxy;
5886
5887 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005888 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5889 curproxy->id, trule->act_prm.trk_ctr.table.n,
5890 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005891 cfgerr++;
5892 }
5893 else if (target->table.size == 0) {
5894 Alert("Proxy '%s': table '%s' used but not configured.\n",
5895 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5896 cfgerr++;
5897 }
5898 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005899 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 +02005900 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5901 cfgerr++;
5902 }
5903 else {
5904 free(trule->act_prm.trk_ctr.table.n);
5905 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005906 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005907 * to pass a list of counters to track and allocate them right here using
5908 * stktable_alloc_data_type().
5909 */
5910 }
5911 }
5912
Emeric Brun32da3c42010-09-23 18:39:19 +02005913 if (curproxy->table.peers.name) {
5914 struct peers *curpeers = peers;
5915
5916 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5917 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5918 free((void *)curproxy->table.peers.name);
5919 curproxy->table.peers.p = peers;
5920 break;
5921 }
5922 }
5923
5924 if (!curpeers) {
5925 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5926 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005927 free((void *)curproxy->table.peers.name);
5928 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005929 cfgerr++;
5930 }
5931 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005932 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5933 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005934 free((void *)curproxy->table.peers.name);
5935 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005936 cfgerr++;
5937 }
5938 }
5939
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005940 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005941 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005942 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5943 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5944 "proxy", curproxy->id);
5945 cfgerr++;
5946 goto out_uri_auth_compat;
5947 }
5948
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005949 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005950 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005951 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005952 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005953
Willy Tarreau95fa4692010-02-01 13:05:50 +01005954 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5955 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005956
5957 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005958 uri_auth_compat_req[i++] = "realm";
5959 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5960 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005961
Willy Tarreau95fa4692010-02-01 13:05:50 +01005962 uri_auth_compat_req[i++] = "unless";
5963 uri_auth_compat_req[i++] = "{";
5964 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5965 uri_auth_compat_req[i++] = "}";
5966 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005967
Willy Tarreauff011f22011-01-06 17:51:27 +01005968 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5969 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005970 cfgerr++;
5971 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005972 }
5973
Willy Tarreauff011f22011-01-06 17:51:27 +01005974 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005975
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005976 if (curproxy->uri_auth->auth_realm) {
5977 free(curproxy->uri_auth->auth_realm);
5978 curproxy->uri_auth->auth_realm = NULL;
5979 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005980
5981 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005982 }
5983out_uri_auth_compat:
5984
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005985 cfgerr += acl_find_targets(curproxy);
5986
Willy Tarreau2738a142006-07-08 17:28:09 +02005987 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005988 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005989 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005990 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005991 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005992 " | While not properly invalid, you will certainly encounter various problems\n"
5993 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005994 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005995 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005996 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005997 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005998
Willy Tarreau1fa31262007-12-03 00:36:16 +01005999 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6000 * We must still support older configurations, so let's find out whether those
6001 * parameters have been set or must be copied from contimeouts.
6002 */
6003 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006004 if (!curproxy->timeout.tarpit ||
6005 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006006 /* tarpit timeout not set. We search in the following order:
6007 * default.tarpit, curr.connect, default.connect.
6008 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006009 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006010 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006011 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006012 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006013 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006014 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006015 }
6016 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006017 (!curproxy->timeout.queue ||
6018 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006019 /* queue timeout not set. We search in the following order:
6020 * default.queue, curr.connect, default.connect.
6021 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006022 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006023 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006024 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006025 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006026 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006027 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006028 }
6029 }
6030
Willy Tarreau1620ec32011-08-06 17:05:02 +02006031 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006032 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6033 curproxy->check_req = (char *)malloc(curproxy->check_len);
6034 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006035 }
6036
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006037 /* The small pools required for the capture lists */
6038 if (curproxy->nb_req_cap)
6039 curproxy->req_cap_pool = create_pool("ptrcap",
6040 curproxy->nb_req_cap * sizeof(char *),
6041 MEM_F_SHARED);
6042 if (curproxy->nb_rsp_cap)
6043 curproxy->rsp_cap_pool = create_pool("ptrcap",
6044 curproxy->nb_rsp_cap * sizeof(char *),
6045 MEM_F_SHARED);
6046
Willy Tarreaubaaee002006-06-26 02:48:02 +02006047 /* first, we will invert the servers list order */
6048 newsrv = NULL;
6049 while (curproxy->srv) {
6050 struct server *next;
6051
6052 next = curproxy->srv->next;
6053 curproxy->srv->next = newsrv;
6054 newsrv = curproxy->srv;
6055 if (!next)
6056 break;
6057 curproxy->srv = next;
6058 }
6059
Willy Tarreaudd701652010-05-25 23:03:02 +02006060 /* assign automatic UIDs to servers which don't have one yet */
6061 next_id = 1;
6062 newsrv = curproxy->srv;
6063 while (newsrv != NULL) {
6064 if (!newsrv->puid) {
6065 /* server ID not set, use automatic numbering with first
6066 * spare entry starting with next_svid.
6067 */
6068 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6069 newsrv->conf.id.key = newsrv->puid = next_id;
6070 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6071 }
6072 next_id++;
6073 newsrv = newsrv->next;
6074 }
6075
Willy Tarreau20697042007-11-15 23:26:18 +01006076 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006077 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006078
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006079 /* We have to initialize the server lookup mechanism depending
6080 * on what LB algorithm was choosen.
6081 */
6082
6083 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6084 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6085 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006086 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6087 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6088 init_server_map(curproxy);
6089 } else {
6090 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6091 fwrr_init_server_groups(curproxy);
6092 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006093 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006094
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006095 case BE_LB_KIND_LC:
6096 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006097 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006098 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006099
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006100 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006101 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6102 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6103 chash_init_server_tree(curproxy);
6104 } else {
6105 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6106 init_server_map(curproxy);
6107 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006108 break;
6109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110
6111 if (curproxy->options & PR_O_LOGASAP)
6112 curproxy->to_log &= ~LW_BYTES;
6113
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006114 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006115 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006116 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6117 proxy_type_str(curproxy), curproxy->id);
6118 err_code |= ERR_WARN;
6119 }
6120
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006121 if (curproxy->mode != PR_MODE_HTTP) {
6122 int optnum;
6123
6124 if (curproxy->options & PR_O_COOK_ANY) {
6125 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6126 proxy_type_str(curproxy), curproxy->id);
6127 err_code |= ERR_WARN;
6128 }
6129
6130 if (curproxy->uri_auth) {
6131 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6132 proxy_type_str(curproxy), curproxy->id);
6133 err_code |= ERR_WARN;
6134 curproxy->uri_auth = NULL;
6135 }
6136
Willy Tarreau87cf5142011-08-19 22:57:24 +02006137 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006138 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6139 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6140 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006141 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006142 }
6143
6144 if (curproxy->options & PR_O_ORGTO) {
6145 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6146 "originalto", proxy_type_str(curproxy), curproxy->id);
6147 err_code |= ERR_WARN;
6148 curproxy->options &= ~PR_O_ORGTO;
6149 }
6150
6151 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6152 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6153 (curproxy->cap & cfg_opts[optnum].cap) &&
6154 (curproxy->options & cfg_opts[optnum].val)) {
6155 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6156 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6157 err_code |= ERR_WARN;
6158 curproxy->options &= ~cfg_opts[optnum].val;
6159 }
6160 }
6161
6162 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6163 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6164 (curproxy->cap & cfg_opts2[optnum].cap) &&
6165 (curproxy->options2 & cfg_opts2[optnum].val)) {
6166 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6167 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6168 err_code |= ERR_WARN;
6169 curproxy->options2 &= ~cfg_opts2[optnum].val;
6170 }
6171 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006172
Willy Tarreauefa5f512010-03-30 20:13:29 +02006173#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006174 if (curproxy->bind_hdr_occ) {
6175 curproxy->bind_hdr_occ = 0;
6176 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6177 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6178 err_code |= ERR_WARN;
6179 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006180#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006181 }
6182
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006184 * ensure that we're not cross-dressing a TCP server into HTTP.
6185 */
6186 newsrv = curproxy->srv;
6187 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006188 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006189 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6190 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006191 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006192 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006193
Willy Tarreau0cec3312011-10-31 13:49:26 +01006194 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6195 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6196 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6197 err_code |= ERR_WARN;
6198 }
6199
Willy Tarreauefa5f512010-03-30 20:13:29 +02006200#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006201 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6202 newsrv->bind_hdr_occ = 0;
6203 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6204 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6205 err_code |= ERR_WARN;
6206 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006207#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006208 newsrv = newsrv->next;
6209 }
6210
6211 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006212 * If this server supports a maxconn parameter, it needs a dedicated
6213 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006214 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215 */
6216 newsrv = curproxy->srv;
6217 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006218 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006219 /* Only 'minconn' was specified, or it was higher than or equal
6220 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6221 * this will avoid further useless expensive computations.
6222 */
6223 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006224 } else if (newsrv->maxconn && !newsrv->minconn) {
6225 /* minconn was not specified, so we set it to maxconn */
6226 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006227 }
6228
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006229 if (newsrv->trackit) {
6230 struct proxy *px;
6231 struct server *srv;
6232 char *pname, *sname;
6233
6234 pname = newsrv->trackit;
6235 sname = strrchr(pname, '/');
6236
6237 if (sname)
6238 *sname++ = '\0';
6239 else {
6240 sname = pname;
6241 pname = NULL;
6242 }
6243
6244 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006245 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006246 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006247 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6248 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006249 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006250 cfgerr++;
6251 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006252 }
6253 } else
6254 px = curproxy;
6255
6256 srv = findserver(px, sname);
6257 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006258 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6259 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006260 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006261 cfgerr++;
6262 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006263 }
6264
6265 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006266 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006267 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006268 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006269 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006270 cfgerr++;
6271 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006272 }
6273
6274 if (curproxy != px &&
6275 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006276 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006277 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006278 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006279 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006280 cfgerr++;
6281 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006282 }
6283
Willy Tarreau44267702011-10-28 15:35:33 +02006284 newsrv->track = srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006285 newsrv->tracknext = srv->tracknext;
6286 srv->tracknext = newsrv;
6287
6288 free(newsrv->trackit);
6289 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006290 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006291 newsrv = newsrv->next;
6292 }
6293
Willy Tarreauc1a21672009-08-16 22:37:44 +02006294 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006295 curproxy->accept = frontend_accept;
6296
Willy Tarreauc1a21672009-08-16 22:37:44 +02006297 if (curproxy->tcp_req.inspect_delay ||
6298 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006299 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006300
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006301 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006302 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006303 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006304 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006305
6306 /* both TCP and HTTP must check switching rules */
6307 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6308 }
6309
6310 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006311 if (curproxy->tcp_req.inspect_delay ||
6312 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6313 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6314
Emeric Brun97679e72010-09-23 17:56:44 +02006315 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6316 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6317
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006318 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006319 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006320 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006321 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006322
6323 /* If the backend does requires RDP cookie persistence, we have to
6324 * enable the corresponding analyser.
6325 */
6326 if (curproxy->options2 & PR_O2_RDPC_PRST)
6327 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6328 }
6329
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006330 listener = NULL;
6331 while (curproxy->listen) {
6332 struct listener *next;
6333
6334 next = curproxy->listen->next;
6335 curproxy->listen->next = listener;
6336 listener = curproxy->listen;
6337
6338 if (!next)
6339 break;
6340
6341 curproxy->listen = next;
6342 }
6343
Willy Tarreaue6b98942007-10-29 01:09:36 +01006344 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006345 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006346 listener = curproxy->listen;
6347 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006348 if (!listener->luid) {
6349 /* listener ID not set, use automatic numbering with first
6350 * spare entry starting with next_luid.
6351 */
6352 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6353 listener->conf.id.key = listener->luid = next_id;
6354 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006355 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006356 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006357
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006358 /* enable separate counters */
6359 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6360 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6361 if (!listener->name) {
6362 sprintf(trash, "sock-%d", listener->luid);
6363 listener->name = strdup(trash);
6364 }
6365 }
6366
Willy Tarreaue6b98942007-10-29 01:09:36 +01006367 if (curproxy->options & PR_O_TCP_NOLING)
6368 listener->options |= LI_O_NOLINGER;
6369 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006370 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006371 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006372 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006373 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006374 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006375 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006376
Willy Tarreau8a956912010-10-15 14:27:08 +02006377 if (listener->options & LI_O_ACC_PROXY)
6378 listener->analysers |= AN_REQ_DECODE_PROXY;
6379
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006380 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6381 listener->options |= LI_O_TCP_RULES;
6382
Willy Tarreaude3041d2010-05-31 10:56:17 +02006383 if (curproxy->mon_mask.s_addr)
6384 listener->options |= LI_O_CHK_MONNET;
6385
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006386 /* smart accept mode is automatic in HTTP mode */
6387 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6388 (curproxy->mode == PR_MODE_HTTP &&
6389 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6390 listener->options |= LI_O_NOQUICKACK;
6391
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006392 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006393 listener = listener->next;
6394 }
6395
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006396 /* Check multi-process mode compatibility for the current proxy */
6397 if (global.nbproc > 1) {
6398 int nbproc = 0;
6399 if (curproxy->bind_proc) {
6400 int proc;
6401 for (proc = 0; proc < global.nbproc; proc++) {
6402 if (curproxy->bind_proc & (1 << proc)) {
6403 nbproc++;
6404 }
6405 }
6406 } else {
6407 nbproc = global.nbproc;
6408 }
6409 if (curproxy->table.peers.name) {
6410 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6411 curproxy->id);
6412 cfgerr++;
6413 }
6414 if (nbproc > 1) {
6415 if (curproxy->uri_auth) {
6416 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6417 curproxy->id);
6418 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6419 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6420 curproxy->id);
6421 }
6422 }
6423 if (curproxy->appsession_name) {
6424 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6425 curproxy->id);
6426 }
6427 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6428 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6429 curproxy->id);
6430 }
6431 }
6432 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006433
6434 /* create the task associated with the proxy */
6435 curproxy->task = task_new();
6436 if (curproxy->task) {
6437 curproxy->task->context = curproxy;
6438 curproxy->task->process = manage_proxy;
6439 /* no need to queue, it will be done automatically if some
6440 * listener gets limited.
6441 */
6442 curproxy->task->expire = TICK_ETERNITY;
6443 } else {
6444 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6445 curproxy->id);
6446 cfgerr++;
6447 }
6448
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 curproxy = curproxy->next;
6450 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006451
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006452 /* Check multi-process mode compatibility */
6453 if (global.nbproc > 1) {
6454 if (global.stats_fe) {
6455 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6456 }
6457 }
6458
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006459 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6460 struct auth_users *curuser;
6461 int g;
6462
6463 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6464 unsigned int group_mask = 0;
6465 char *group = NULL;
6466
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006467 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006468 continue;
6469
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006470 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006471
6472 for (g = 0; g < curuserlist->grpcnt; g++)
6473 if (!strcmp(curuserlist->groups[g], group))
6474 break;
6475
6476 if (g == curuserlist->grpcnt) {
6477 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6478 curuserlist->name, group, curuser->user);
6479 err_code |= ERR_ALERT | ERR_FATAL;
6480 goto out;
6481 }
6482
6483 group_mask |= (1 << g);
6484 }
6485
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006486 free(curuser->u.groups);
6487 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006488 }
6489
6490 for (g = 0; g < curuserlist->grpcnt; g++) {
6491 char *user = NULL;
6492
6493 if (!curuserlist->groupusers[g])
6494 continue;
6495
6496 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6497 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6498 if (!strcmp(curuser->user, user))
6499 break;
6500
6501 if (!curuser) {
6502 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6503 curuserlist->name, user, curuserlist->groups[g]);
6504 err_code |= ERR_ALERT | ERR_FATAL;
6505 goto out;
6506 }
6507
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006508 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006509 }
6510
6511 free(curuserlist->groupusers[g]);
6512 }
6513
6514 free(curuserlist->groupusers);
6515
6516#ifdef DEBUG_AUTH
6517 for (g = 0; g < curuserlist->grpcnt; g++) {
6518 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6519
6520 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6521 if (curuser->group_mask & (1 << g))
6522 fprintf(stderr, " %s", curuser->user);
6523 }
6524
6525 fprintf(stderr, "\n");
6526 }
6527#endif
6528
Willy Tarreaufbb78422011-06-05 15:38:35 +02006529 }
6530
6531 /* automatically compute fullconn if not set. We must not do it in the
6532 * loop above because cross-references are not yet fully resolved.
6533 */
6534 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6535 /* If <fullconn> is not set, let's set it to 10% of the sum of
6536 * the possible incoming frontend's maxconns.
6537 */
6538 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6539 struct proxy *fe;
6540 int total = 0;
6541
6542 /* sum up the number of maxconns of frontends which
6543 * reference this backend at least once or which are
6544 * the same one ('listen').
6545 */
6546 for (fe = proxy; fe; fe = fe->next) {
6547 struct switching_rule *rule;
6548 struct hdr_exp *exp;
6549 int found = 0;
6550
6551 if (!(fe->cap & PR_CAP_FE))
6552 continue;
6553
6554 if (fe == curproxy) /* we're on a "listen" instance */
6555 found = 1;
6556
6557 if (fe->defbe.be == curproxy) /* "default_backend" */
6558 found = 1;
6559
6560 /* check if a "use_backend" rule matches */
6561 if (!found) {
6562 list_for_each_entry(rule, &fe->switching_rules, list) {
6563 if (rule->be.backend == curproxy) {
6564 found = 1;
6565 break;
6566 }
6567 }
6568 }
6569
6570 /* check if a "reqsetbe" rule matches */
6571 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6572 if (exp->action == ACT_SETBE &&
6573 (struct proxy *)exp->replace == curproxy) {
6574 found = 1;
6575 break;
6576 }
6577 }
6578
6579 /* now we've checked all possible ways to reference a backend
6580 * from a frontend.
6581 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006582 if (!found)
6583 continue;
6584 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006585 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006586 /* we have the sum of the maxconns in <total>. We only
6587 * keep 10% of that sum to set the default fullconn, with
6588 * a hard minimum of 1 (to avoid a divide by zero).
6589 */
6590 curproxy->fullconn = (total + 9) / 10;
6591 if (!curproxy->fullconn)
6592 curproxy->fullconn = 1;
6593 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006594 }
6595
Willy Tarreau056f5682010-06-06 15:51:11 +02006596 /* initialize stick-tables on backend capable proxies. This must not
6597 * be done earlier because the data size may be discovered while parsing
6598 * other proxies.
6599 */
6600 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006601 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006602
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006603 /*
6604 * Recount currently required checks.
6605 */
6606
6607 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6608 int optnum;
6609
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006610 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6611 if (curproxy->options & cfg_opts[optnum].val)
6612 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006613
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006614 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6615 if (curproxy->options2 & cfg_opts2[optnum].val)
6616 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006617 }
6618
Willy Tarreau122541c2011-09-07 21:24:49 +02006619 if (peers) {
6620 struct peers *curpeers = peers, **last;
6621 struct peer *p, *pb;
6622
6623 /* Remove all peers sections which don't have a valid listener.
6624 * This can happen when a peers section is never referenced and
6625 * does not contain a local peer.
6626 */
6627 last = &peers;
6628 while (*last) {
6629 curpeers = *last;
6630 if (curpeers->peers_fe) {
6631 last = &curpeers->next;
6632 continue;
6633 }
6634
6635 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6636 curpeers->id, localpeer);
6637
6638 p = curpeers->remote;
6639 while (p) {
6640 pb = p->next;
6641 free(p->id);
6642 free(p);
6643 p = pb;
6644 }
6645
6646 /* Destroy and unlink this curpeers section.
6647 * Note: curpeers is backed up into *last.
6648 */
6649 free(curpeers->id);
6650 curpeers = curpeers->next;
6651 free(*last);
6652 *last = curpeers;
6653 }
6654 }
6655
Willy Tarreauac1932d2011-10-24 19:14:41 +02006656 if (!global.tune.max_http_hdr)
6657 global.tune.max_http_hdr = MAX_HTTP_HDR;
6658
Willy Tarreau34eb6712011-10-24 18:15:04 +02006659 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006660 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006661 MEM_F_SHARED);
6662
Willy Tarreaubb925012009-07-23 13:36:36 +02006663 if (cfgerr > 0)
6664 err_code |= ERR_ALERT | ERR_FATAL;
6665 out:
6666 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006667}
6668
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006669/*
6670 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6671 * parsing sessions.
6672 */
6673void cfg_register_keywords(struct cfg_kw_list *kwl)
6674{
6675 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6676}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006677
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006678/*
6679 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6680 */
6681void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6682{
6683 LIST_DEL(&kwl->list);
6684 LIST_INIT(&kwl->list);
6685}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006686
6687/*
6688 * Local variables:
6689 * c-indent-level: 8
6690 * c-basic-offset: 8
6691 * End:
6692 */