blob: 48d2617144638796c0f66e0b39d5f98afb8f1ae6 [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 Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200163 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100164 { NULL, 0, 0, 0 }
165};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166
Willy Tarreau6daf3432008-01-22 16:44:08 +0100167static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
169int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100170int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200172/* List head of all known configuration keywords */
173static struct cfg_kw_list cfg_keywords = {
174 .list = LIST_HEAD_INIT(cfg_keywords.list)
175};
176
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177/*
178 * converts <str> to a list of listeners which are dynamically allocated.
179 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
180 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
181 * - <port> is a numerical port from 1 to 65535 ;
182 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
183 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200184 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200185 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100186static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187{
188 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100189 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 int port, end;
191
192 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200193
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 while (next && *next) {
195 struct sockaddr_storage ss;
196
197 str = next;
198 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100199 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 *next++ = 0;
201 }
202
Emeric Bruned760922010-10-22 17:59:25 +0200203 if (*str == '/') {
204 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
205 /* so compute max path */
206 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
207 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 +0200208
Emeric Bruned760922010-10-22 17:59:25 +0200209 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100210 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
211 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200212 goto fail;
213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200216 ss.ss_family = AF_UNIX;
217 if (global.unix_bind.prefix) {
218 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
219 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 }
Emeric Bruned760922010-10-22 17:59:25 +0200221 else {
222 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
223 }
224 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
226 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 ss2 = str2sa_range(str, &port, &end);
230 if (!ss2) {
231 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
232 file, line, str);
233 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100236 if (!port) {
237 Alert("parsing [%s:%d] : missing port number: '%s'\n",
238 file, line, str);
239 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 /* OK the address looks correct */
243 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Emeric Bruned760922010-10-22 17:59:25 +0200245 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
247 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200248 goto fail;
249 }
250
251 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
253 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200254 goto fail;
255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256 }
257
258 for (; port <= end; port++) {
259 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200260 l->next = curproxy->listen;
261 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262
263 l->fd = -1;
264 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 l->state = LI_INIT;
266
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100267 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200268 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100269 tcpv4_add_listener(l);
270 }
Emeric Bruned760922010-10-22 17:59:25 +0200271 else if (ss.ss_family == AF_INET6) {
272 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
273 tcpv6_add_listener(l);
274 }
275 else {
276 l->perm.ux.gid = l->perm.ux.uid = -1;
277 l->perm.ux.mode = 0;
278 uxst_add_listener(l);
279 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200280
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200281 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200283 } /* end for(port) */
284 } /* end while(next) */
285 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200287 fail:
288 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200289 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290}
291
Willy Tarreau977b8e42006-12-29 14:19:17 +0100292/*
293 * Sends a warning if proxy <proxy> does not have at least one of the
294 * capabilities in <cap>. An optionnal <hint> may be added at the end
295 * of the warning to help the user. Returns 1 if a warning was emitted
296 * or 0 if the condition is valid.
297 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100298int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299{
300 char *msg;
301
302 switch (cap) {
303 case PR_CAP_BE: msg = "no backend"; break;
304 case PR_CAP_FE: msg = "no frontend"; break;
305 case PR_CAP_RS: msg = "no ruleset"; break;
306 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
307 default: msg = "not enough"; break;
308 }
309
310 if (!(proxy->cap & cap)) {
311 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100312 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100313 return 1;
314 }
315 return 0;
316}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317
Willy Tarreau61d18892009-03-31 10:49:21 +0200318/* Report a warning if a rule is placed after a 'block' rule.
319 * Return 1 if the warning has been emitted, otherwise 0.
320 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100321int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200322{
323 if (!LIST_ISEMPTY(&proxy->block_cond)) {
324 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
325 file, line, arg);
326 return 1;
327 }
328 return 0;
329}
330
331/* Report a warning if a rule is placed after a reqrewrite rule.
332 * Return 1 if the warning has been emitted, otherwise 0.
333 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100334int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200335{
336 if (proxy->req_exp) {
337 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
338 file, line, arg);
339 return 1;
340 }
341 return 0;
342}
343
344/* Report a warning if a rule is placed after a reqadd rule.
345 * Return 1 if the warning has been emitted, otherwise 0.
346 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100347int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200348{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100349 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200350 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
351 file, line, arg);
352 return 1;
353 }
354 return 0;
355}
356
357/* Report a warning if a rule is placed after a redirect rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100360int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200361{
362 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
370/* Report a warning if a rule is placed after a 'use_backend' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
375 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
383/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
387 warnif_rule_after_reqadd(proxy, file, line, arg) ||
388 warnif_rule_after_redirect(proxy, file, line, arg) ||
389 warnif_rule_after_use_backend(proxy, file, line, arg);
390}
391
392/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100393int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200394{
395 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
396 warnif_rule_after_redirect(proxy, file, line, arg) ||
397 warnif_rule_after_use_backend(proxy, file, line, arg);
398}
399
400/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100401int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200402{
403 return warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100407/* Report it if a request ACL condition uses some response-only parameters. It
408 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
409 * Note that <cond> may be NULL and then will be ignored.
410 */
411static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
412{
413 struct acl *acl;
414
415 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
416 return 0;
417
418 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
419 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
420 file, line, acl ? acl->name : "(unknown)");
421 return ERR_WARN;
422}
423
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100424/* Report it if a request ACL condition uses some request-only volatile parameters.
425 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
426 * Note that <cond> may be NULL and then will be ignored.
427 */
428static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
429{
430 struct acl *acl;
431
432 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
433 return 0;
434
435 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
436 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
437 file, line, acl ? acl->name : "(unknown)");
438 return ERR_WARN;
439}
440
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100441
Willy Tarreaubaaee002006-06-26 02:48:02 +0200442/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200443 * parse a line in a <global> section. Returns the error code, 0 if OK, or
444 * any combination of :
445 * - ERR_ABORT: must abort ASAP
446 * - ERR_FATAL: we can continue parsing but not start the service
447 * - ERR_WARN: a warning has been emitted
448 * - ERR_ALERT: an alert has been emitted
449 * Only the two first ones can stop processing, the two others are just
450 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200451 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200452int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453{
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455
456 if (!strcmp(args[0], "global")) { /* new section */
457 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459 }
460 else if (!strcmp(args[0], "daemon")) {
461 global.mode |= MODE_DAEMON;
462 }
463 else if (!strcmp(args[0], "debug")) {
464 global.mode |= MODE_DEBUG;
465 }
466 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100467 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200468 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200469 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100470 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 }
472 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100478 else if (!strcmp(args[0], "nosplice")) {
479 global.tune.options &= ~GTUNE_USE_SPLICE;
480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "quiet")) {
482 global.mode |= MODE_QUIET;
483 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200484 else if (!strcmp(args[0], "tune.maxpollevents")) {
485 if (global.tune.maxpollevents != 0) {
486 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200487 err_code |= ERR_ALERT;
488 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200489 }
490 if (*(args[1]) == 0) {
491 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200492 err_code |= ERR_ALERT | ERR_FATAL;
493 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200494 }
495 global.tune.maxpollevents = atol(args[1]);
496 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100497 else if (!strcmp(args[0], "tune.maxaccept")) {
498 if (global.tune.maxaccept != 0) {
499 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200500 err_code |= ERR_ALERT;
501 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100502 }
503 if (*(args[1]) == 0) {
504 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200505 err_code |= ERR_ALERT | ERR_FATAL;
506 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100507 }
508 global.tune.maxaccept = atol(args[1]);
509 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200510 else if (!strcmp(args[0], "tune.chksize")) {
511 if (*(args[1]) == 0) {
512 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
513 err_code |= ERR_ALERT | ERR_FATAL;
514 goto out;
515 }
516 global.tune.chksize = atol(args[1]);
517 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200518 else if (!strcmp(args[0], "tune.bufsize")) {
519 if (*(args[1]) == 0) {
520 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
521 err_code |= ERR_ALERT | ERR_FATAL;
522 goto out;
523 }
524 global.tune.bufsize = atol(args[1]);
525 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
526 global.tune.maxrewrite = global.tune.bufsize / 2;
527 }
528 else if (!strcmp(args[0], "tune.maxrewrite")) {
529 if (*(args[1]) == 0) {
530 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
531 err_code |= ERR_ALERT | ERR_FATAL;
532 goto out;
533 }
534 global.tune.maxrewrite = atol(args[1]);
535 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
536 global.tune.maxrewrite = global.tune.bufsize / 2;
537 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100538 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
539 if (global.tune.client_rcvbuf != 0) {
540 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
541 err_code |= ERR_ALERT;
542 goto out;
543 }
544 if (*(args[1]) == 0) {
545 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
546 err_code |= ERR_ALERT | ERR_FATAL;
547 goto out;
548 }
549 global.tune.client_rcvbuf = atol(args[1]);
550 }
551 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
552 if (global.tune.server_rcvbuf != 0) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.tune.server_rcvbuf = atol(args[1]);
563 }
564 else if (!strcmp(args[0], "tune.sndbuf.client")) {
565 if (global.tune.client_sndbuf != 0) {
566 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT;
568 goto out;
569 }
570 if (*(args[1]) == 0) {
571 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT | ERR_FATAL;
573 goto out;
574 }
575 global.tune.client_sndbuf = atol(args[1]);
576 }
577 else if (!strcmp(args[0], "tune.sndbuf.server")) {
578 if (global.tune.server_sndbuf != 0) {
579 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT;
581 goto out;
582 }
583 if (*(args[1]) == 0) {
584 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
585 err_code |= ERR_ALERT | ERR_FATAL;
586 goto out;
587 }
588 global.tune.server_sndbuf = atol(args[1]);
589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 else if (!strcmp(args[0], "uid")) {
591 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200592 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200593 err_code |= ERR_ALERT;
594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 }
601 global.uid = atol(args[1]);
602 }
603 else if (!strcmp(args[0], "gid")) {
604 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200605 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200606 err_code |= ERR_ALERT;
607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 }
609 if (*(args[1]) == 0) {
610 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT | ERR_FATAL;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 global.gid = atol(args[1]);
615 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 /* user/group name handling */
617 else if (!strcmp(args[0], "user")) {
618 struct passwd *ha_user;
619 if (global.uid != 0) {
620 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
622 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 }
624 errno = 0;
625 ha_user = getpwnam(args[1]);
626 if (ha_user != NULL) {
627 global.uid = (int)ha_user->pw_uid;
628 }
629 else {
630 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 +0200631 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200632 }
633 }
634 else if (!strcmp(args[0], "group")) {
635 struct group *ha_group;
636 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200637 Alert("parsing [%s:%d] : gid/group was 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_group = getgrnam(args[1]);
643 if (ha_group != NULL) {
644 global.gid = (int)ha_group->gr_gid;
645 }
646 else {
647 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 +0200648 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200649 }
650 }
651 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nbproc")) {
653 if (global.nbproc != 0) {
654 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200655 err_code |= ERR_ALERT;
656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200657 }
658 if (*(args[1]) == 0) {
659 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200660 err_code |= ERR_ALERT | ERR_FATAL;
661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200662 }
663 global.nbproc = atol(args[1]);
664 }
665 else if (!strcmp(args[0], "maxconn")) {
666 if (global.maxconn != 0) {
667 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200668 err_code |= ERR_ALERT;
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 }
671 if (*(args[1]) == 0) {
672 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 global.maxconn = atol(args[1]);
677#ifdef SYSTEM_MAXCONN
678 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
679 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);
680 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200681 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683#endif /* SYSTEM_MAXCONN */
684 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100685 else if (!strcmp(args[0], "maxpipes")) {
686 if (global.maxpipes != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100695 }
696 global.maxpipes = atol(args[1]);
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "ulimit-n")) {
699 if (global.rlimit_nofile != 0) {
700 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200701 err_code |= ERR_ALERT;
702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200703 }
704 if (*(args[1]) == 0) {
705 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT | ERR_FATAL;
707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200708 }
709 global.rlimit_nofile = atol(args[1]);
710 }
711 else if (!strcmp(args[0], "chroot")) {
712 if (global.chroot != NULL) {
713 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200714 err_code |= ERR_ALERT;
715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200716 }
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200721 }
722 global.chroot = strdup(args[1]);
723 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200724 else if (!strcmp(args[0], "description")) {
725 int i, len=0;
726 char *d;
727
728 if (!*args[1]) {
729 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
730 file, linenum, args[0]);
731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
733 }
734
735 for(i=1; *args[i]; i++)
736 len += strlen(args[i])+1;
737
738 if (global.desc)
739 free(global.desc);
740
741 global.desc = d = (char *)calloc(1, len);
742
743 d += sprintf(d, "%s", args[1]);
744 for(i=2; *args[i]; i++)
745 d += sprintf(d, " %s", args[i]);
746 }
747 else if (!strcmp(args[0], "node")) {
748 int i;
749 char c;
750
751 for (i=0; args[1][i]; i++) {
752 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100753 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
754 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 break;
756 }
757
758 if (!i || args[1][i]) {
759 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
760 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (global.node)
767 free(global.node);
768
769 global.node = strdup(args[1]);
770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 else if (!strcmp(args[0], "pidfile")) {
772 if (global.pidfile != NULL) {
773 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200774 err_code |= ERR_ALERT;
775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200776 }
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 global.pidfile = strdup(args[1]);
783 }
Emeric Bruned760922010-10-22 17:59:25 +0200784 else if (!strcmp(args[0], "unix-bind")) {
785 int cur_arg = 1;
786 while (*(args[cur_arg])) {
787 if (!strcmp(args[cur_arg], "prefix")) {
788 if (global.unix_bind.prefix != NULL) {
789 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
790 err_code |= ERR_ALERT;
791 cur_arg += 2;
792 continue;
793 }
794
795 if (*(args[cur_arg+1]) == 0) {
796 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
797 err_code |= ERR_ALERT | ERR_FATAL;
798 goto out;
799 }
800 global.unix_bind.prefix = strdup(args[cur_arg+1]);
801 cur_arg += 2;
802 continue;
803 }
804
805 if (!strcmp(args[cur_arg], "mode")) {
806
807 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
808 cur_arg += 2;
809 continue;
810 }
811
812 if (!strcmp(args[cur_arg], "uid")) {
813
814 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
815 cur_arg += 2;
816 continue;
817 }
818
819 if (!strcmp(args[cur_arg], "gid")) {
820
821 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
822 cur_arg += 2;
823 continue;
824 }
825
826 if (!strcmp(args[cur_arg], "user")) {
827 struct passwd *user;
828
829 user = getpwnam(args[cur_arg + 1]);
830 if (!user) {
831 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
832 file, linenum, args[0], args[cur_arg + 1 ]);
833 err_code |= ERR_ALERT | ERR_FATAL;
834 goto out;
835 }
836
837 global.unix_bind.ux.uid = user->pw_uid;
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "group")) {
843 struct group *group;
844
845 group = getgrnam(args[cur_arg + 1]);
846 if (!group) {
847 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
848 file, linenum, args[0], args[cur_arg + 1 ]);
849 err_code |= ERR_ALERT | ERR_FATAL;
850 goto out;
851 }
852
853 global.unix_bind.ux.gid = group->gr_gid;
854 cur_arg += 2;
855 continue;
856 }
857
858 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
859 file, linenum, args[0]);
860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
862 }
863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100865 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200866 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867
868 if (*(args[1]) == 0 || *(args[2]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872 }
873
874 facility = get_log_facility(args[2]);
875 if (facility < 0) {
876 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
878 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879 }
880
881 level = 7; /* max syslog level = debug */
882 if (*(args[3])) {
883 level = get_log_level(args[3]);
884 if (level < 0) {
885 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200886 err_code |= ERR_ALERT | ERR_FATAL;
887 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 }
889 }
890
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200891 minlvl = 0; /* limit syslog level to this level (emerg) */
892 if (*(args[4])) {
893 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200895 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200896 err_code |= ERR_ALERT | ERR_FATAL;
897 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200898 }
899 }
900
Robert Tsai81ae1952007-12-05 10:47:29 +0100901 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100902 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100903 if (!sk) {
904 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100905 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100909 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100910 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100911 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100912 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100913 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100917 logsrv.addr = *sk;
918 if (!get_host_port(&logsrv.addr))
919 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921
922 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100923 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 global.logfac1 = facility;
925 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200926 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100929 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 global.logfac2 = facility;
931 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200932 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934 else {
935 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200938 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100939 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
940 char *name;
941 int len;
942
943 if (global.log_send_hostname != NULL) {
944 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
945 err_code |= ERR_ALERT;
946 goto out;
947 }
948
949 if (*(args[1]))
950 name = args[1];
951 else
952 name = hostname;
953
954 len = strlen(name);
955
956 /* We'll add a space after the name to respect the log format */
957 free(global.log_send_hostname);
958 global.log_send_hostname = malloc(len + 2);
959 snprintf(global.log_send_hostname, len + 2, "%s ", name);
960 }
Kevinm48936af2010-12-22 16:08:21 +0000961 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 free(global.log_tag);
968 global.log_tag = strdup(args[1]);
969 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200970 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
971 if (global.spread_checks != 0) {
972 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200973 err_code |= ERR_ALERT;
974 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200975 }
976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200980 }
981 global.spread_checks = atol(args[1]);
982 if (global.spread_checks < 0 || global.spread_checks > 50) {
983 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200988 struct cfg_kw_list *kwl;
989 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200990 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200991
992 list_for_each_entry(kwl, &cfg_keywords.list, list) {
993 for (index = 0; kwl->kw[index].kw != NULL; index++) {
994 if (kwl->kw[index].section != CFG_GLOBAL)
995 continue;
996 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
997 /* prepare error message just in case */
998 snprintf(trash, sizeof(trash),
999 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001000 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1001 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001002 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001005 else if (rc > 0) {
1006 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001007 err_code |= ERR_WARN;
1008 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001009 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001010 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001011 }
1012 }
1013 }
1014
Willy Tarreaubaaee002006-06-26 02:48:02 +02001015 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001016 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001018
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 out:
1020 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021}
1022
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001023void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001025 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026 defproxy.mode = PR_MODE_TCP;
1027 defproxy.state = PR_STNEW;
1028 defproxy.maxconn = cfg_maxpconn;
1029 defproxy.conn_retries = CONN_RETRIES;
1030 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001031
1032 defproxy.defsrv.inter = DEF_CHKINTR;
1033 defproxy.defsrv.fastinter = 0;
1034 defproxy.defsrv.downinter = 0;
1035 defproxy.defsrv.rise = DEF_RISETIME;
1036 defproxy.defsrv.fall = DEF_FALLTIME;
1037 defproxy.defsrv.check_port = 0;
1038 defproxy.defsrv.maxqueue = 0;
1039 defproxy.defsrv.minconn = 0;
1040 defproxy.defsrv.maxconn = 0;
1041 defproxy.defsrv.slowstart = 0;
1042 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1043 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1044 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045}
1046
Willy Tarreauade5ec42010-01-28 19:33:49 +01001047
1048static int create_cond_regex_rule(const char *file, int line,
1049 struct proxy *px, int dir, int action, int flags,
1050 const char *cmd, const char *reg, const char *repl,
1051 const char **cond_start)
1052{
1053 regex_t *preg = NULL;
1054 const char *err;
1055 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001056 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001057
1058 if (px == &defproxy) {
1059 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto err;
1062 }
1063
1064 if (*reg == 0) {
1065 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1066 err_code |= ERR_ALERT | ERR_FATAL;
1067 goto err;
1068 }
1069
1070 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1071 err_code |= ERR_WARN;
1072
Willy Tarreau5321c422010-01-28 20:35:13 +01001073 if (cond_start &&
1074 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1075 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1076 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1077 file, line, cmd);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto err;
1080 }
1081 }
1082 else if (cond_start && **cond_start) {
1083 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1084 file, line, cmd, *cond_start);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto err;
1087 }
1088
1089 if (dir == ACL_DIR_REQ)
1090 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001091 else
1092 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001093
Willy Tarreauade5ec42010-01-28 19:33:49 +01001094 preg = calloc(1, sizeof(regex_t));
1095 if (!preg) {
1096 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1097 err_code = ERR_ALERT | ERR_FATAL;
1098 goto err;
1099 }
1100
1101 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1102 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1103 err_code = ERR_ALERT | ERR_FATAL;
1104 goto err;
1105 }
1106
1107 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001108 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001109 if (repl && err) {
1110 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1111 file, line, cmd, *err);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115
1116 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1117 err_code |= ERR_WARN;
1118
1119 return err_code;
1120 err:
1121 free(preg);
1122 return err_code;
1123}
1124
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001126 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001127 * Returns the error code, 0 if OK, or any combination of :
1128 * - ERR_ABORT: must abort ASAP
1129 * - ERR_FATAL: we can continue parsing but not start the service
1130 * - ERR_WARN: a warning has been emitted
1131 * - ERR_ALERT: an alert has been emitted
1132 * Only the two first ones can stop processing, the two others are just
1133 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001135int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1136{
1137 static struct peers *curpeers = NULL;
1138 struct peer *newpeer = NULL;
1139 const char *err;
1140 int err_code = 0;
1141
1142 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1143
1144 err = invalid_char(args[1]);
1145 if (err) {
1146 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1147 file, linenum, *err, args[0], args[1]);
1148 err_code |= ERR_ALERT | ERR_FATAL;
1149 }
1150
1151 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1152 /*
1153 * If there are two proxies with the same name only following
1154 * combinations are allowed:
1155 */
1156 if (strcmp(curpeers->id, args[1]) == 0) {
1157 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1158 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1159 err_code |= ERR_WARN;
1160 }
1161 }
1162
1163 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1164 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1165 err_code |= ERR_ALERT | ERR_ABORT;
1166 goto out;
1167 }
1168
1169 curpeers->next = peers;
1170 peers = curpeers;
1171 curpeers->conf.file = file;
1172 curpeers->conf.line = linenum;
1173 curpeers->last_change = now.tv_sec;
1174 curpeers->id = strdup(args[1]);
1175 }
1176 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1177 char *rport, *raddr;
1178 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001179 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001180
1181 if (!*args[2]) {
1182 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1183 file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 err = invalid_char(args[1]);
1189 if (err) {
1190 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1191 file, linenum, *err, args[1]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
1195
1196 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == 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 /* the peers are linked backwards first */
1203 curpeers->count++;
1204 newpeer->next = curpeers->remote;
1205 curpeers->remote = newpeer;
1206 newpeer->peers = curpeers;
1207 newpeer->conf.file = file;
1208 newpeer->conf.line = linenum;
1209
1210 newpeer->last_change = now.tv_sec;
1211 newpeer->id = strdup(args[1]);
1212
1213 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001214 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001215 if (rport) {
1216 *rport++ = 0;
1217 realport = atol(rport);
1218 }
1219 if (!realport) {
1220 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224
Willy Tarreaufab5a432011-03-04 15:31:53 +01001225 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001226 free(raddr);
1227 if (!sk) {
1228 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1229 err_code |= ERR_ALERT | ERR_FATAL;
1230 goto out;
1231 }
1232 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001233 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001234
1235 if (strcmp(newpeer->id, localpeer) == 0) {
1236 /* Current is local peer, it define a frontend */
1237 newpeer->local = 1;
1238
1239 if (!curpeers->peers_fe) {
1240 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1242 err_code |= ERR_ALERT | ERR_ABORT;
1243 goto out;
1244 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001245
Willy Tarreau237250c2011-07-29 01:49:03 +02001246 init_new_proxy(curpeers->peers_fe);
1247 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001248
1249 curpeers->peers_fe->last_change = now.tv_sec;
1250 curpeers->peers_fe->id = strdup(args[1]);
1251 curpeers->peers_fe->cap = PR_CAP_FE;
1252 curpeers->peers_fe->maxconn = 65000;
1253 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1254 curpeers->peers_fe->timeout.connect = 5000;
1255 curpeers->peers_fe->accept = peer_accept;
1256 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001257 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001258 err_code |= ERR_FATAL;
1259 goto out;
1260 }
1261 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1262 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1263 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1264 curpeers->peers_fe->listen->accept = session_accept;
1265 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1266 curpeers->peers_fe->listen->handler = process_session;
1267 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1268 }
1269 }
1270 } /* neither "peer" nor "peers" */
1271 else if (*args[0] != 0) {
1272 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
1275 }
1276
1277out:
1278 return err_code;
1279}
1280
1281
Willy Tarreau3842f002009-06-14 11:39:52 +02001282int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001283{
1284 static struct proxy *curproxy = NULL;
1285 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001286 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001287 int rc;
1288 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001289 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001290 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001291
Willy Tarreau977b8e42006-12-29 14:19:17 +01001292 if (!strcmp(args[0], "listen"))
1293 rc = PR_CAP_LISTEN;
1294 else if (!strcmp(args[0], "frontend"))
1295 rc = PR_CAP_FE | PR_CAP_RS;
1296 else if (!strcmp(args[0], "backend"))
1297 rc = PR_CAP_BE | PR_CAP_RS;
1298 else if (!strcmp(args[0], "ruleset"))
1299 rc = PR_CAP_RS;
1300 else
1301 rc = PR_CAP_NONE;
1302
1303 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001304 if (!*args[1]) {
1305 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1306 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1307 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001308 err_code |= ERR_ALERT | ERR_ABORT;
1309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001311
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001312 err = invalid_char(args[1]);
1313 if (err) {
1314 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1315 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001316 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001317 }
1318
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001319 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1320 /*
1321 * If there are two proxies with the same name only following
1322 * combinations are allowed:
1323 *
1324 * listen backend frontend ruleset
1325 * listen - - - -
1326 * backend - - OK -
1327 * frontend - OK - -
1328 * ruleset - - - -
1329 */
1330
1331 if (!strcmp(curproxy->id, args[1]) &&
1332 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1333 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001334 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1335 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1336 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001337 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001338 }
1339 }
1340
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1342 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001343 err_code |= ERR_ALERT | ERR_ABORT;
1344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001346
Willy Tarreau97cb7802010-01-03 20:23:58 +01001347 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 curproxy->next = proxy;
1349 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001350 curproxy->conf.file = file;
1351 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001352 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001354 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355
1356 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001357 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001358 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001359 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001360 err_code |= ERR_FATAL;
1361 goto out;
1362 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001363 new = curproxy->listen;
1364 while (new != last) {
1365 new->conf.file = file;
1366 new->conf.line = linenum;
1367 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001368 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 }
1371
1372 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001373 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001374 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001375
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001377 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001378 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001379 curproxy->no_options = defproxy.no_options;
1380 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001381 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001382 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001383 curproxy->except_net = defproxy.except_net;
1384 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001385 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001386 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001388 if (defproxy.fwdfor_hdr_len) {
1389 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1390 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1391 }
1392
Willy Tarreaub86db342009-11-30 11:50:16 +01001393 if (defproxy.orgto_hdr_len) {
1394 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1395 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1396 }
1397
Willy Tarreau977b8e42006-12-29 14:19:17 +01001398 if (curproxy->cap & PR_CAP_FE) {
1399 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001400 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001401 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001402
1403 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001404 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1405 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001406
1407 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1408 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001409
Willy Tarreau977b8e42006-12-29 14:19:17 +01001410 if (curproxy->cap & PR_CAP_BE) {
1411 curproxy->fullconn = defproxy.fullconn;
1412 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001414 if (defproxy.check_req) {
1415 curproxy->check_req = calloc(1, defproxy.check_len);
1416 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1417 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001418 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001420 if (defproxy.expect_str) {
1421 curproxy->expect_str = strdup(defproxy.expect_str);
1422 if (defproxy.expect_regex) {
1423 /* note: this regex is known to be valid */
1424 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1425 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1426 }
1427 }
1428
Willy Tarreau977b8e42006-12-29 14:19:17 +01001429 if (defproxy.cookie_name)
1430 curproxy->cookie_name = strdup(defproxy.cookie_name);
1431 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001432 if (defproxy.cookie_domain)
1433 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001434
Willy Tarreau31936852010-10-06 16:59:56 +02001435 if (defproxy.cookie_maxidle)
1436 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1437
1438 if (defproxy.cookie_maxlife)
1439 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1440
Emeric Brun647caf12009-06-30 17:57:00 +02001441 if (defproxy.rdp_cookie_name)
1442 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1443 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1444
Willy Tarreau01732802007-11-01 22:48:15 +01001445 if (defproxy.url_param_name)
1446 curproxy->url_param_name = strdup(defproxy.url_param_name);
1447 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001448
Benoitaffb4812009-03-25 13:02:10 +01001449 if (defproxy.hh_name)
1450 curproxy->hh_name = strdup(defproxy.hh_name);
1451 curproxy->hh_len = defproxy.hh_len;
1452 curproxy->hh_match_domain = defproxy.hh_match_domain;
1453
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001454 if (defproxy.iface_name)
1455 curproxy->iface_name = strdup(defproxy.iface_name);
1456 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001459 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001460 if (defproxy.capture_name)
1461 curproxy->capture_name = strdup(defproxy.capture_name);
1462 curproxy->capture_namelen = defproxy.capture_namelen;
1463 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001467 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001468 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001469 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001470 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471 curproxy->uri_auth = defproxy.uri_auth;
1472 curproxy->mon_net = defproxy.mon_net;
1473 curproxy->mon_mask = defproxy.mon_mask;
1474 if (defproxy.monitor_uri)
1475 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1476 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001477 if (defproxy.defbe.name)
1478 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001479 }
1480
1481 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001482 curproxy->timeout.connect = defproxy.timeout.connect;
1483 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001484 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001485 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001486 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001487 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001488 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001489 curproxy->source_addr = defproxy.source_addr;
1490 }
1491
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492 curproxy->mode = defproxy.mode;
1493 curproxy->logfac1 = defproxy.logfac1;
1494 curproxy->logsrv1 = defproxy.logsrv1;
1495 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001496 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 curproxy->logfac2 = defproxy.logfac2;
1498 curproxy->logsrv2 = defproxy.logsrv2;
1499 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001500 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001502 curproxy->conf.used_listener_id = EB_ROOT;
1503 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001504
Willy Tarreau93893792009-07-23 13:19:11 +02001505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506 }
1507 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1508 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001509 /* FIXME-20070101: we should do this too at the end of the
1510 * config parsing to free all default values.
1511 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001512 free(defproxy.check_req);
1513 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001514 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001515 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001516 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001517 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001518 free(defproxy.capture_name);
1519 free(defproxy.monitor_uri);
1520 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001521 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001522 free(defproxy.fwdfor_hdr_name);
1523 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001524 free(defproxy.orgto_hdr_name);
1525 defproxy.orgto_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001526 free(defproxy.expect_str);
1527 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001528
Willy Tarreaua534fea2008-08-03 12:19:50 +02001529 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001530 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001531
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 /* we cannot free uri_auth because it might already be used */
1533 init_default_instance();
1534 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001535 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537 }
1538 else if (curproxy == NULL) {
1539 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001542 }
1543
Willy Tarreau977b8e42006-12-29 14:19:17 +01001544
1545 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001546 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001547 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001548 int cur_arg;
1549
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 if (curproxy == &defproxy) {
1551 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001552 err_code |= ERR_ALERT | ERR_FATAL;
1553 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001555 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001556 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557
Emeric Bruned760922010-10-22 17:59:25 +02001558 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001559 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001564
1565 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001566
1567 /* NOTE: the following line might create several listeners if there
1568 * are comma-separated IPs or port ranges. So all further processing
1569 * will have to be applied to all listeners created after last_listen.
1570 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001571 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001572 err_code |= ERR_ALERT | ERR_FATAL;
1573 goto out;
1574 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001575
Willy Tarreau90a570f2009-10-04 20:54:54 +02001576 new_listen = curproxy->listen;
1577 while (new_listen != last_listen) {
1578 new_listen->conf.file = file;
1579 new_listen->conf.line = linenum;
1580 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001581 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001582 }
1583
Emeric Bruned760922010-10-22 17:59:25 +02001584 /* Set default global rights and owner for unix bind */
1585 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1586 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1587 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001588 cur_arg = 2;
1589 while (*(args[cur_arg])) {
1590 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1591#ifdef SO_BINDTODEVICE
1592 struct listener *l;
1593
Emeric Bruned760922010-10-22 17:59:25 +02001594 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1595 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1596 file, linenum, args[0], args[cur_arg]);
1597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
1599 }
1600
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001601 if (!*args[cur_arg + 1]) {
1602 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1603 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
1605 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001606 }
1607
1608 for (l = curproxy->listen; l != last_listen; l = l->next)
1609 l->interface = strdup(args[cur_arg + 1]);
1610
1611 global.last_checks |= LSTCHK_NETADM;
1612
1613 cur_arg += 2;
1614 continue;
1615#else
1616 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1617 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
1619 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001620#endif
1621 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001622 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1623#ifdef TCP_MAXSEG
1624 struct listener *l;
1625 int mss;
1626
Emeric Bruned760922010-10-22 17:59:25 +02001627 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1628 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1629 file, linenum, args[0], args[cur_arg]);
1630 err_code |= ERR_ALERT | ERR_FATAL;
1631 goto out;
1632 }
1633
Willy Tarreaube1b9182009-06-14 18:48:19 +02001634 if (!*args[cur_arg + 1]) {
1635 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1636 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001637 err_code |= ERR_ALERT | ERR_FATAL;
1638 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001639 }
1640
Willy Tarreau48a7e722010-12-24 15:26:39 +01001641 mss = atoi(args[cur_arg + 1]);
1642 if (!mss || abs(mss) > 65535) {
1643 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001647 }
1648
1649 for (l = curproxy->listen; l != last_listen; l = l->next)
1650 l->maxseg = mss;
1651
1652 cur_arg += 2;
1653 continue;
1654#else
1655 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1656 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001657 err_code |= ERR_ALERT | ERR_FATAL;
1658 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001659#endif
1660 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001661
1662 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1663#ifdef TCP_DEFER_ACCEPT
1664 struct listener *l;
1665
1666 for (l = curproxy->listen; l != last_listen; l = l->next)
1667 l->options |= LI_O_DEF_ACCEPT;
1668
1669 cur_arg ++;
1670 continue;
1671#else
1672 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1673 file, linenum, args[0], args[cur_arg]);
1674 err_code |= ERR_ALERT | ERR_FATAL;
1675 goto out;
1676#endif
1677 }
1678
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001679 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001680#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001681 struct listener *l;
1682
Emeric Bruned760922010-10-22 17:59:25 +02001683 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1684 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1685 file, linenum, args[0], args[cur_arg]);
1686 err_code |= ERR_ALERT | ERR_FATAL;
1687 goto out;
1688 }
1689
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001690 for (l = curproxy->listen; l != last_listen; l = l->next)
1691 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001692
1693 cur_arg ++;
1694 continue;
1695#else
1696 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1697 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001698 err_code |= ERR_ALERT | ERR_FATAL;
1699 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001700#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001701 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001702
Willy Tarreau8a956912010-10-15 14:27:08 +02001703 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1704 struct listener *l;
1705
1706 for (l = curproxy->listen; l != last_listen; l = l->next)
1707 l->options |= LI_O_ACC_PROXY;
1708
1709 cur_arg ++;
1710 continue;
1711 }
1712
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001713 if (!strcmp(args[cur_arg], "name")) {
1714 struct listener *l;
1715
1716 for (l = curproxy->listen; l != last_listen; l = l->next)
1717 l->name = strdup(args[cur_arg + 1]);
1718
1719 cur_arg += 2;
1720 continue;
1721 }
1722
1723 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001724 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001725 struct listener *l;
1726
1727 if (curproxy->listen->next != last_listen) {
1728 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1729 file, linenum, args[cur_arg]);
1730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
1732 }
1733
1734 if (!*args[cur_arg + 1]) {
1735 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1736 file, linenum, args[cur_arg]);
1737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
1739 }
1740
1741 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001742 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001743
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001744 if (curproxy->listen->luid <= 0) {
1745 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001746 file, linenum);
1747 err_code |= ERR_ALERT | ERR_FATAL;
1748 goto out;
1749 }
1750
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001751 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1752 if (node) {
1753 l = container_of(node, struct listener, conf.id);
1754 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1755 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
1759 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1760
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001761 cur_arg += 2;
1762 continue;
1763 }
1764
Emeric Bruned760922010-10-22 17:59:25 +02001765 if (!strcmp(args[cur_arg], "mode")) {
1766
1767 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1768 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1769 file, linenum, args[0], args[cur_arg]);
1770 err_code |= ERR_ALERT | ERR_FATAL;
1771 goto out;
1772 }
1773
1774 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1775
1776 cur_arg += 2;
1777 continue;
1778 }
1779
1780 if (!strcmp(args[cur_arg], "uid")) {
1781
1782 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1783 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1784 file, linenum, args[0], args[cur_arg]);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788
1789 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1790 cur_arg += 2;
1791 continue;
1792 }
1793
1794 if (!strcmp(args[cur_arg], "gid")) {
1795
1796 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1797 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1798 file, linenum, args[0], args[cur_arg]);
1799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
1801 }
1802
1803 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1804 cur_arg += 2;
1805 continue;
1806 }
1807
1808 if (!strcmp(args[cur_arg], "user")) {
1809 struct passwd *user;
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 user = getpwnam(args[cur_arg + 1]);
1818 if (!user) {
1819 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1820 file, linenum, args[0], args[cur_arg + 1 ]);
1821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
1823 }
1824
1825 curproxy->listen->perm.ux.uid = user->pw_uid;
1826 cur_arg += 2;
1827 continue;
1828 }
1829
1830 if (!strcmp(args[cur_arg], "group")) {
1831 struct group *group;
1832
1833 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1834 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1835 file, linenum, args[0], args[cur_arg]);
1836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
1838 }
1839 group = getgrnam(args[cur_arg + 1]);
1840 if (!group) {
1841 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1842 file, linenum, args[0], args[cur_arg + 1 ]);
1843 err_code |= ERR_ALERT | ERR_FATAL;
1844 goto out;
1845 }
1846
1847 curproxy->listen->perm.ux.gid = group->gr_gid;
1848 cur_arg += 2;
1849 continue;
1850 }
1851
Willy Tarreau8a956912010-10-15 14:27:08 +02001852 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001853 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001856 }
Willy Tarreau93893792009-07-23 13:19:11 +02001857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 }
1859 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1860 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1861 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1862 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001863 err_code |= ERR_ALERT | ERR_FATAL;
1864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001866 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001867 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001868
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869 /* flush useless bits */
1870 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001872 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001873 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001874 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001875 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001876
Willy Tarreau1c47f852006-07-09 08:22:27 +02001877 if (!*args[1]) {
1878 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1879 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001882 }
1883
Willy Tarreaua534fea2008-08-03 12:19:50 +02001884 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001885 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001886 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001887 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001888 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1889
Willy Tarreau93893792009-07-23 13:19:11 +02001890 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1893 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1894 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1895 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1896 else {
1897 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001898 err_code |= ERR_ALERT | ERR_FATAL;
1899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900 }
1901 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001902 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001903 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001904
1905 if (curproxy == &defproxy) {
1906 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1907 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001910 }
1911
1912 if (!*args[1]) {
1913 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1914 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001917 }
1918
1919 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001920 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001921
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001922 if (curproxy->uuid <= 0) {
1923 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001924 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001925 err_code |= ERR_ALERT | ERR_FATAL;
1926 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001927 }
1928
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001929 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1930 if (node) {
1931 struct proxy *target = container_of(node, struct proxy, conf.id);
1932 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1933 file, linenum, proxy_type_str(curproxy), curproxy->id,
1934 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
1937 }
1938 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001939 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001940 else if (!strcmp(args[0], "description")) {
1941 int i, len=0;
1942 char *d;
1943
Cyril Bonté99ed3272010-01-24 23:29:44 +01001944 if (curproxy == &defproxy) {
1945 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1946 file, linenum, args[0]);
1947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
1949 }
1950
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001951 if (!*args[1]) {
1952 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1953 file, linenum, args[0]);
1954 return -1;
1955 }
1956
1957 for(i=1; *args[i]; i++)
1958 len += strlen(args[i])+1;
1959
1960 d = (char *)calloc(1, len);
1961 curproxy->desc = d;
1962
1963 d += sprintf(d, "%s", args[1]);
1964 for(i=2; *args[i]; i++)
1965 d += sprintf(d, " %s", args[i]);
1966
1967 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001968 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1969 curproxy->state = PR_STSTOPPED;
1970 }
1971 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1972 curproxy->state = PR_STNEW;
1973 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001974 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1975 int cur_arg = 1;
1976 unsigned int set = 0;
1977
1978 while (*args[cur_arg]) {
1979 int u;
1980 if (strcmp(args[cur_arg], "all") == 0) {
1981 set = 0;
1982 break;
1983 }
1984 else if (strcmp(args[cur_arg], "odd") == 0) {
1985 set |= 0x55555555;
1986 }
1987 else if (strcmp(args[cur_arg], "even") == 0) {
1988 set |= 0xAAAAAAAA;
1989 }
1990 else {
1991 u = str2uic(args[cur_arg]);
1992 if (u < 1 || u > 32) {
1993 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1994 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001995 err_code |= ERR_ALERT | ERR_FATAL;
1996 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001997 }
1998 if (u > global.nbproc) {
1999 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2000 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002002 }
2003 set |= 1 << (u - 1);
2004 }
2005 cur_arg++;
2006 }
2007 curproxy->bind_proc = set;
2008 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002009 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002010 if (curproxy == &defproxy) {
2011 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002014 }
2015
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002016 err = invalid_char(args[1]);
2017 if (err) {
2018 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2019 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002020 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002021 }
2022
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002023 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2024 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2025 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002028 }
2029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2031 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032
Willy Tarreau977b8e42006-12-29 14:19:17 +01002033 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 if (*(args[1]) == 0) {
2037 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2038 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002042
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002043 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002044 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002045 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002046 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002047 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048 curproxy->cookie_name = strdup(args[1]);
2049 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002050
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 cur_arg = 2;
2052 while (*(args[cur_arg])) {
2053 if (!strcmp(args[cur_arg], "rewrite")) {
2054 curproxy->options |= PR_O_COOK_RW;
2055 }
2056 else if (!strcmp(args[cur_arg], "indirect")) {
2057 curproxy->options |= PR_O_COOK_IND;
2058 }
2059 else if (!strcmp(args[cur_arg], "insert")) {
2060 curproxy->options |= PR_O_COOK_INS;
2061 }
2062 else if (!strcmp(args[cur_arg], "nocache")) {
2063 curproxy->options |= PR_O_COOK_NOC;
2064 }
2065 else if (!strcmp(args[cur_arg], "postonly")) {
2066 curproxy->options |= PR_O_COOK_POST;
2067 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002068 else if (!strcmp(args[cur_arg], "preserve")) {
2069 curproxy->options2 |= PR_O2_COOK_PSV;
2070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 else if (!strcmp(args[cur_arg], "prefix")) {
2072 curproxy->options |= PR_O_COOK_PFX;
2073 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002074 else if (!strcmp(args[cur_arg], "domain")) {
2075 if (!*args[cur_arg + 1]) {
2076 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2077 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002080 }
2081
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002082 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002083 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002084 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2085 " dots nor does not start with a dot."
2086 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002087 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002088 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002089 }
2090
2091 err = invalid_domainchar(args[cur_arg + 1]);
2092 if (err) {
2093 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2094 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002097 }
2098
Willy Tarreau68a897b2009-12-03 23:28:34 +01002099 if (!curproxy->cookie_domain) {
2100 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2101 } else {
2102 /* one domain was already specified, add another one by
2103 * building the string which will be returned along with
2104 * the cookie.
2105 */
2106 char *new_ptr;
2107 int new_len = strlen(curproxy->cookie_domain) +
2108 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2109 new_ptr = malloc(new_len);
2110 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2111 free(curproxy->cookie_domain);
2112 curproxy->cookie_domain = new_ptr;
2113 }
Willy Tarreau31936852010-10-06 16:59:56 +02002114 cur_arg++;
2115 }
2116 else if (!strcmp(args[cur_arg], "maxidle")) {
2117 unsigned int maxidle;
2118 const char *res;
2119
2120 if (!*args[cur_arg + 1]) {
2121 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2122 file, linenum, args[cur_arg]);
2123 err_code |= ERR_ALERT | ERR_FATAL;
2124 goto out;
2125 }
2126
2127 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2128 if (res) {
2129 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2130 file, linenum, *res, args[cur_arg]);
2131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
2133 }
2134 curproxy->cookie_maxidle = maxidle;
2135 cur_arg++;
2136 }
2137 else if (!strcmp(args[cur_arg], "maxlife")) {
2138 unsigned int maxlife;
2139 const char *res;
2140
2141 if (!*args[cur_arg + 1]) {
2142 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2143 file, linenum, args[cur_arg]);
2144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
2146 }
2147
2148 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2149 if (res) {
2150 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2151 file, linenum, *res, args[cur_arg]);
2152 err_code |= ERR_ALERT | ERR_FATAL;
2153 goto out;
2154 }
2155 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002156 cur_arg++;
2157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002159 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 +02002160 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 }
2164 cur_arg++;
2165 }
2166 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2167 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2168 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002169 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 }
2171
2172 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2173 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2174 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002177
2178 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2179 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2180 file, linenum);
2181 err_code |= ERR_ALERT | ERR_FATAL;
2182 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002184 else if (!strcmp(args[0], "persist")) { /* persist */
2185 if (*(args[1]) == 0) {
2186 Alert("parsing [%s:%d] : missing persist method.\n",
2187 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002190 }
2191
2192 if (!strncmp(args[1], "rdp-cookie", 10)) {
2193 curproxy->options2 |= PR_O2_RDPC_PRST;
2194
Emeric Brunb982a3d2010-01-04 15:45:53 +01002195 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002196 const char *beg, *end;
2197
2198 beg = args[1] + 11;
2199 end = strchr(beg, ')');
2200
2201 if (!end || end == beg) {
2202 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2203 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002206 }
2207
2208 free(curproxy->rdp_cookie_name);
2209 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2210 curproxy->rdp_cookie_len = end-beg;
2211 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002212 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002213 free(curproxy->rdp_cookie_name);
2214 curproxy->rdp_cookie_name = strdup("msts");
2215 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2216 }
2217 else { /* syntax */
2218 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2219 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002222 }
2223 }
2224 else {
2225 Alert("parsing [%s:%d] : unknown persist method.\n",
2226 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002229 }
2230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002231 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002232 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002234 if (curproxy == &defproxy) {
2235 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
2238 }
2239
Willy Tarreau977b8e42006-12-29 14:19:17 +01002240 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002242
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002244 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 }
2249 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002250 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 curproxy->appsession_name = strdup(args[1]);
2252 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2253 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002254 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2255 if (err) {
2256 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2257 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002260 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002261 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002262
Willy Tarreau51041c72007-09-09 21:56:53 +02002263 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2264 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002265 err_code |= ERR_ALERT | ERR_ABORT;
2266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002268
2269 cur_arg = 6;
2270 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002271 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2272 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002273 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002274 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002275 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002276 } else if (!strcmp(args[cur_arg], "prefix")) {
2277 curproxy->options2 |= PR_O2_AS_PFX;
2278 } else if (!strcmp(args[cur_arg], "mode")) {
2279 if (!*args[cur_arg + 1]) {
2280 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2281 file, linenum, args[0], args[cur_arg]);
2282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
2284 }
2285
2286 cur_arg++;
2287 if (!strcmp(args[cur_arg], "query-string")) {
2288 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2289 curproxy->options2 |= PR_O2_AS_M_QS;
2290 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2291 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2292 curproxy->options2 |= PR_O2_AS_M_PP;
2293 } else {
2294 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002299 cur_arg++;
2300 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 } /* Url App Session */
2302 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002303 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002305
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002307 if (curproxy == &defproxy) {
2308 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
2311 }
2312
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 if (*(args[4]) == 0) {
2314 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2315 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002316 err_code |= ERR_ALERT | ERR_FATAL;
2317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002319 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 curproxy->capture_name = strdup(args[2]);
2321 curproxy->capture_namelen = strlen(curproxy->capture_name);
2322 curproxy->capture_len = atol(args[4]);
2323 if (curproxy->capture_len >= CAPTURE_LEN) {
2324 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2325 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 curproxy->capture_len = CAPTURE_LEN - 1;
2328 }
2329 curproxy->to_log |= LW_COOKIE;
2330 }
2331 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2332 struct cap_hdr *hdr;
2333
2334 if (curproxy == &defproxy) {
2335 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 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 }
2339
2340 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2341 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2342 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 }
2346
2347 hdr = calloc(sizeof(struct cap_hdr), 1);
2348 hdr->next = curproxy->req_cap;
2349 hdr->name = strdup(args[3]);
2350 hdr->namelen = strlen(args[3]);
2351 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002352 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 hdr->index = curproxy->nb_req_cap++;
2354 curproxy->req_cap = hdr;
2355 curproxy->to_log |= LW_REQHDR;
2356 }
2357 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2358 struct cap_hdr *hdr;
2359
2360 if (curproxy == &defproxy) {
2361 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 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
2365
2366 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2367 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2368 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002369 err_code |= ERR_ALERT | ERR_FATAL;
2370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
2372 hdr = calloc(sizeof(struct cap_hdr), 1);
2373 hdr->next = curproxy->rsp_cap;
2374 hdr->name = strdup(args[3]);
2375 hdr->namelen = strlen(args[3]);
2376 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002377 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002378 hdr->index = curproxy->nb_rsp_cap++;
2379 curproxy->rsp_cap = hdr;
2380 curproxy->to_log |= LW_RSPHDR;
2381 }
2382 else {
2383 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2384 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_ALERT | ERR_FATAL;
2386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387 }
2388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002389 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002391 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002392
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 if (*(args[1]) == 0) {
2394 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002396 err_code |= ERR_ALERT | ERR_FATAL;
2397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 }
2399 curproxy->conn_retries = atol(args[1]);
2400 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002401 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002402 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002403
2404 if (curproxy == &defproxy) {
2405 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
2408 }
2409
Willy Tarreauff011f22011-01-06 17:51:27 +01002410 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 +01002411 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2412 file, linenum, args[0]);
2413 err_code |= ERR_WARN;
2414 }
2415
Willy Tarreauff011f22011-01-06 17:51:27 +01002416 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002417
Willy Tarreauff011f22011-01-06 17:51:27 +01002418 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002419 err_code |= ERR_ALERT | ERR_ABORT;
2420 goto out;
2421 }
2422
Willy Tarreauff011f22011-01-06 17:51:27 +01002423 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2424 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002425 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002426 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002427 if (curproxy == &defproxy) {
2428 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002429 err_code |= ERR_ALERT | ERR_FATAL;
2430 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002431 }
2432
Willy Tarreauef6494c2010-01-28 17:12:36 +01002433 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002434 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2435 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002438 }
2439
Willy Tarreauef6494c2010-01-28 17:12:36 +01002440 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002441 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2442 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002445 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002446
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002447 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002448 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002449 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002450 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002451 struct redirect_rule *rule;
2452 int cur_arg;
2453 int type = REDIRECT_TYPE_NONE;
2454 int code = 302;
2455 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002456 char *cookie = NULL;
2457 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002458 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002459
Cyril Bonté99ed3272010-01-24 23:29:44 +01002460 if (curproxy == &defproxy) {
2461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
2464 }
2465
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002466 cur_arg = 1;
2467 while (*(args[cur_arg])) {
2468 if (!strcmp(args[cur_arg], "location")) {
2469 if (!*args[cur_arg + 1]) {
2470 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2471 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002474 }
2475
2476 type = REDIRECT_TYPE_LOCATION;
2477 cur_arg++;
2478 destination = args[cur_arg];
2479 }
2480 else if (!strcmp(args[cur_arg], "prefix")) {
2481 if (!*args[cur_arg + 1]) {
2482 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2483 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002484 err_code |= ERR_ALERT | ERR_FATAL;
2485 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002486 }
2487
2488 type = REDIRECT_TYPE_PREFIX;
2489 cur_arg++;
2490 destination = args[cur_arg];
2491 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002492 else if (!strcmp(args[cur_arg], "set-cookie")) {
2493 if (!*args[cur_arg + 1]) {
2494 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2495 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002498 }
2499
2500 cur_arg++;
2501 cookie = args[cur_arg];
2502 cookie_set = 1;
2503 }
2504 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2505 if (!*args[cur_arg + 1]) {
2506 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2507 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002510 }
2511
2512 cur_arg++;
2513 cookie = args[cur_arg];
2514 cookie_set = 0;
2515 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002516 else if (!strcmp(args[cur_arg],"code")) {
2517 if (!*args[cur_arg + 1]) {
2518 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 }
2523 cur_arg++;
2524 code = atol(args[cur_arg]);
2525 if (code < 301 || code > 303) {
2526 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2527 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530 }
2531 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002532 else if (!strcmp(args[cur_arg],"drop-query")) {
2533 flags |= REDIRECT_FLAG_DROP_QS;
2534 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002535 else if (!strcmp(args[cur_arg],"append-slash")) {
2536 flags |= REDIRECT_FLAG_APPEND_SLASH;
2537 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002538 else if (strcmp(args[cur_arg], "if") == 0 ||
2539 strcmp(args[cur_arg], "unless") == 0) {
2540 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2541 if (!cond) {
2542 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2543 file, linenum, args[0]);
2544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
2546 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002547 break;
2548 }
2549 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002550 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 +02002551 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002554 }
2555 cur_arg++;
2556 }
2557
2558 if (type == REDIRECT_TYPE_NONE) {
2559 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2560 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002563 }
2564
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002565 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2566 rule->cond = cond;
2567 rule->rdr_str = strdup(destination);
2568 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002569 if (cookie) {
2570 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002571 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002572 */
2573 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002574 if (cookie_set) {
2575 rule->cookie_str = malloc(rule->cookie_len + 10);
2576 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2577 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2578 rule->cookie_len += 9;
2579 } else {
2580 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002581 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002582 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2583 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002584 }
2585 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 rule->type = type;
2587 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002588 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002589 LIST_INIT(&rule->list);
2590 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002591 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2592 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002593 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002594 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002595 struct switching_rule *rule;
2596
Willy Tarreaub099aca2008-10-12 17:26:37 +02002597 if (curproxy == &defproxy) {
2598 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002601 }
2602
Willy Tarreau55ea7572007-06-17 19:56:27 +02002603 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002605
2606 if (*(args[1]) == 0) {
2607 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002610 }
2611
Willy Tarreauef6494c2010-01-28 17:12:36 +01002612 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002613 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2614 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002617 }
2618
Willy Tarreauef6494c2010-01-28 17:12:36 +01002619 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002620 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002621 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002624 }
2625
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002626 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002627
Willy Tarreau55ea7572007-06-17 19:56:27 +02002628 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2629 rule->cond = cond;
2630 rule->be.name = strdup(args[1]);
2631 LIST_INIT(&rule->list);
2632 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2633 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002634 else if ((!strcmp(args[0], "force-persist")) ||
2635 (!strcmp(args[0], "ignore-persist"))) {
2636 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002637
2638 if (curproxy == &defproxy) {
2639 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643
2644 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2645 err_code |= ERR_WARN;
2646
Willy Tarreauef6494c2010-01-28 17:12:36 +01002647 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002648 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2649 file, linenum, args[0]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653
Willy Tarreauef6494c2010-01-28 17:12:36 +01002654 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002655 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2656 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
2659 }
2660
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002661 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002662
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002663 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002664 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002665 if (!strcmp(args[0], "force-persist")) {
2666 rule->type = PERSIST_TYPE_FORCE;
2667 } else {
2668 rule->type = PERSIST_TYPE_IGNORE;
2669 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002670 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002671 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002672 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002673 else if (!strcmp(args[0], "stick-table")) {
2674 int myidx = 1;
2675
Emeric Brun32da3c42010-09-23 18:39:19 +02002676 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002677 curproxy->table.type = (unsigned int)-1;
2678 while (*args[myidx]) {
2679 const char *err;
2680
2681 if (strcmp(args[myidx], "size") == 0) {
2682 myidx++;
2683 if (!*(args[myidx])) {
2684 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2685 file, linenum, args[myidx-1]);
2686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
2688 }
2689 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2690 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2691 file, linenum, *err, args[myidx-1]);
2692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002695 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002696 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002697 else if (strcmp(args[myidx], "peers") == 0) {
2698 myidx++;
2699 if (!*(args[myidx])) {
2700 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2701 file, linenum, args[myidx-1]);
2702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
2704 }
2705 curproxy->table.peers.name = strdup(args[myidx++]);
2706 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002707 else if (strcmp(args[myidx], "expire") == 0) {
2708 myidx++;
2709 if (!*(args[myidx])) {
2710 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2711 file, linenum, args[myidx-1]);
2712 err_code |= ERR_ALERT | ERR_FATAL;
2713 goto out;
2714 }
2715 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2716 if (err) {
2717 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2718 file, linenum, *err, args[myidx-1]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002723 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002724 }
2725 else if (strcmp(args[myidx], "nopurge") == 0) {
2726 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002727 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002728 }
2729 else if (strcmp(args[myidx], "type") == 0) {
2730 myidx++;
2731 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2732 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2733 file, linenum, args[myidx]);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002737 /* myidx already points to next arg */
2738 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002739 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002740 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002741 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002742
2743 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002744 nw = args[myidx];
2745 while (*nw) {
2746 /* the "store" keyword supports a comma-separated list */
2747 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002748 sa = NULL; /* store arg */
2749 while (*nw && *nw != ',') {
2750 if (*nw == '(') {
2751 *nw = 0;
2752 sa = ++nw;
2753 while (*nw != ')') {
2754 if (!*nw) {
2755 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2756 file, linenum, args[0], cw);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
2760 nw++;
2761 }
2762 *nw = '\0';
2763 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002764 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002765 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002766 if (*nw)
2767 *nw++ = '\0';
2768 type = stktable_get_data_type(cw);
2769 if (type < 0) {
2770 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2771 file, linenum, args[0], cw);
2772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
2774 }
Willy Tarreauac782882010-06-20 10:41:54 +02002775
2776 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2777 switch (err) {
2778 case PE_NONE: break;
2779 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002780 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2781 file, linenum, args[0], cw);
2782 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002783 break;
2784
2785 case PE_ARG_MISSING:
2786 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2787 file, linenum, args[0], cw);
2788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
2790
2791 case PE_ARG_NOT_USED:
2792 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2793 file, linenum, args[0], cw);
2794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
2796
2797 default:
2798 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2799 file, linenum, args[0], cw);
2800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002802 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002803 }
2804 myidx++;
2805 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002806 else {
2807 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2808 file, linenum, args[myidx]);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002811 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002812 }
2813
2814 if (!curproxy->table.size) {
2815 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2816 file, linenum);
2817 err_code |= ERR_ALERT | ERR_FATAL;
2818 goto out;
2819 }
2820
2821 if (curproxy->table.type == (unsigned int)-1) {
2822 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2823 file, linenum);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
2826 }
2827 }
2828 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002829 struct sticking_rule *rule;
2830 struct pattern_expr *expr;
2831 int myidx = 0;
2832 const char *name = NULL;
2833 int flags;
2834
2835 if (curproxy == &defproxy) {
2836 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840
2841 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2842 err_code |= ERR_WARN;
2843 goto out;
2844 }
2845
2846 myidx++;
2847 if ((strcmp(args[myidx], "store") == 0) ||
2848 (strcmp(args[myidx], "store-request") == 0)) {
2849 myidx++;
2850 flags = STK_IS_STORE;
2851 }
2852 else if (strcmp(args[myidx], "store-response") == 0) {
2853 myidx++;
2854 flags = STK_IS_STORE | STK_ON_RSP;
2855 }
2856 else if (strcmp(args[myidx], "match") == 0) {
2857 myidx++;
2858 flags = STK_IS_MATCH;
2859 }
2860 else if (strcmp(args[myidx], "on") == 0) {
2861 myidx++;
2862 flags = STK_IS_MATCH | STK_IS_STORE;
2863 }
2864 else {
2865 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869
2870 if (*(args[myidx]) == 0) {
2871 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
2874 }
2875
Emeric Brun485479d2010-09-23 18:02:19 +02002876 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002877 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002878 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882
2883 if (flags & STK_ON_RSP) {
2884 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2885 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2886 file, linenum, args[0], expr->fetch->kw);
2887 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002888 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002889 goto out;
2890 }
2891 } else {
2892 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2893 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2894 file, linenum, args[0], expr->fetch->kw);
2895 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002896 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002897 goto out;
2898 }
2899 }
2900
2901 if (strcmp(args[myidx], "table") == 0) {
2902 myidx++;
2903 name = args[myidx++];
2904 }
2905
Willy Tarreauef6494c2010-01-28 17:12:36 +01002906 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2907 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002908 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2909 file, linenum, args[0]);
2910 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002911 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002912 goto out;
2913 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002914 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002915 else if (*(args[myidx])) {
2916 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2917 file, linenum, args[0], args[myidx]);
2918 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002919 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002920 goto out;
2921 }
Emeric Brun97679e72010-09-23 17:56:44 +02002922 if (flags & STK_ON_RSP)
2923 err_code |= warnif_cond_requires_req(cond, file, linenum);
2924 else
2925 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002926
Emeric Brunb982a3d2010-01-04 15:45:53 +01002927 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2928 rule->cond = cond;
2929 rule->expr = expr;
2930 rule->flags = flags;
2931 rule->table.name = name ? strdup(name) : NULL;
2932 LIST_INIT(&rule->list);
2933 if (flags & STK_ON_RSP)
2934 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2935 else
2936 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002938 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002939 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002940 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002941
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2943 curproxy->uri_auth = NULL; /* we must detach from the default config */
2944
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002945 if (!*args[1]) {
2946 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002947 } else if (!strcmp(args[1], "admin")) {
2948 struct stats_admin_rule *rule;
2949
2950 if (curproxy == &defproxy) {
2951 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2952 err_code |= ERR_ALERT | ERR_FATAL;
2953 goto out;
2954 }
2955
2956 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2957 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2958 err_code |= ERR_ALERT | ERR_ABORT;
2959 goto out;
2960 }
2961
2962 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2963 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2964 file, linenum, args[0], args[1]);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
2967 }
2968 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2969 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2970 file, linenum, args[0], args[1]);
2971 err_code |= ERR_ALERT | ERR_FATAL;
2972 goto out;
2973 }
2974
2975 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2976
2977 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
2978 rule->cond = cond;
2979 LIST_INIT(&rule->list);
2980 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002981 } else if (!strcmp(args[1], "uri")) {
2982 if (*(args[2]) == 0) {
2983 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002986 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2987 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002988 err_code |= ERR_ALERT | ERR_ABORT;
2989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002990 }
2991 } else if (!strcmp(args[1], "realm")) {
2992 if (*(args[2]) == 0) {
2993 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2997 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002998 err_code |= ERR_ALERT | ERR_ABORT;
2999 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003000 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003001 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003002 unsigned interval;
3003
3004 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3005 if (err) {
3006 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3007 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003008 err_code |= ERR_ALERT | ERR_FATAL;
3009 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003010 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3011 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_ABORT;
3013 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003014 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003015 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003016 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003017
3018 if (curproxy == &defproxy) {
3019 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3020 err_code |= ERR_ALERT | ERR_FATAL;
3021 goto out;
3022 }
3023
3024 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3025 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3026 err_code |= ERR_ALERT | ERR_ABORT;
3027 goto out;
3028 }
3029
Willy Tarreauff011f22011-01-06 17:51:27 +01003030 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3031 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003032 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3033 file, linenum, args[0]);
3034 err_code |= ERR_WARN;
3035 }
3036
Willy Tarreauff011f22011-01-06 17:51:27 +01003037 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003038
Willy Tarreauff011f22011-01-06 17:51:27 +01003039 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003040 err_code |= ERR_ALERT | ERR_ABORT;
3041 goto out;
3042 }
3043
Willy Tarreauff011f22011-01-06 17:51:27 +01003044 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3045 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 } else if (!strcmp(args[1], "auth")) {
3048 if (*(args[2]) == 0) {
3049 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3053 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_ABORT;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 }
3057 } else if (!strcmp(args[1], "scope")) {
3058 if (*(args[2]) == 0) {
3059 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3063 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_ALERT | ERR_ABORT;
3065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 }
3067 } else if (!strcmp(args[1], "enable")) {
3068 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3069 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003070 err_code |= ERR_ALERT | ERR_ABORT;
3071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003073 } else if (!strcmp(args[1], "hide-version")) {
3074 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3075 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_ALERT | ERR_ABORT;
3077 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003078 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003079 } else if (!strcmp(args[1], "show-legends")) {
3080 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3081 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3082 err_code |= ERR_ALERT | ERR_ABORT;
3083 goto out;
3084 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003085 } else if (!strcmp(args[1], "show-node")) {
3086
3087 if (*args[2]) {
3088 int i;
3089 char c;
3090
3091 for (i=0; args[2][i]; i++) {
3092 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003093 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3094 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003095 break;
3096 }
3097
3098 if (!i || args[2][i]) {
3099 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3100 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3101 file, linenum, args[0], args[1]);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105 }
3106
3107 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3108 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3109 err_code |= ERR_ALERT | ERR_ABORT;
3110 goto out;
3111 }
3112 } else if (!strcmp(args[1], "show-desc")) {
3113 char *desc = NULL;
3114
3115 if (*args[2]) {
3116 int i, len=0;
3117 char *d;
3118
3119 for(i=2; *args[i]; i++)
3120 len += strlen(args[i])+1;
3121
3122 desc = d = (char *)calloc(1, len);
3123
3124 d += sprintf(d, "%s", args[2]);
3125 for(i=3; *args[i]; i++)
3126 d += sprintf(d, " %s", args[i]);
3127 }
3128
3129 if (!*args[2] && !global.desc)
3130 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3131 file, linenum, args[1]);
3132 else {
3133 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3134 free(desc);
3135 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3136 err_code |= ERR_ALERT | ERR_ABORT;
3137 goto out;
3138 }
3139 free(desc);
3140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003142stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003143 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 +01003144 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148 }
3149 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003150 int optnum;
3151
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003152 if (*(args[1]) == '\0') {
3153 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3154 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003158
3159 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3160 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003161 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3162 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3163 file, linenum, cfg_opts[optnum].name);
3164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
3166 }
Willy Tarreau93893792009-07-23 13:19:11 +02003167 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3168 err_code |= ERR_WARN;
3169 goto out;
3170 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003171
Willy Tarreau3842f002009-06-14 11:39:52 +02003172 curproxy->no_options &= ~cfg_opts[optnum].val;
3173 curproxy->options &= ~cfg_opts[optnum].val;
3174
3175 switch (kwm) {
3176 case KWM_STD:
3177 curproxy->options |= cfg_opts[optnum].val;
3178 break;
3179 case KWM_NO:
3180 curproxy->no_options |= cfg_opts[optnum].val;
3181 break;
3182 case KWM_DEF: /* already cleared */
3183 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003184 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003185
Willy Tarreau93893792009-07-23 13:19:11 +02003186 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003187 }
3188 }
3189
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003190 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3191 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003192 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3193 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3194 file, linenum, cfg_opts2[optnum].name);
3195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
3197 }
Willy Tarreau93893792009-07-23 13:19:11 +02003198 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3199 err_code |= ERR_WARN;
3200 goto out;
3201 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003202
Willy Tarreau3842f002009-06-14 11:39:52 +02003203 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3204 curproxy->options2 &= ~cfg_opts2[optnum].val;
3205
3206 switch (kwm) {
3207 case KWM_STD:
3208 curproxy->options2 |= cfg_opts2[optnum].val;
3209 break;
3210 case KWM_NO:
3211 curproxy->no_options2 |= cfg_opts2[optnum].val;
3212 break;
3213 case KWM_DEF: /* already cleared */
3214 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003215 }
Willy Tarreau93893792009-07-23 13:19:11 +02003216 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003217 }
3218 }
3219
Willy Tarreau3842f002009-06-14 11:39:52 +02003220 if (kwm != KWM_STD) {
3221 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003222 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003225 }
3226
Emeric Brun3a058f32009-06-30 18:26:00 +02003227 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003229 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003231 if (*(args[2]) != '\0') {
3232 if (!strcmp(args[2], "clf")) {
3233 curproxy->options2 |= PR_O2_CLFLOG;
3234 } else {
3235 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003238 }
3239 }
3240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003241 else if (!strcmp(args[1], "tcplog"))
3242 /* generate a detailed TCP log */
3243 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 else if (!strcmp(args[1], "tcpka")) {
3245 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003246 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003248
3249 if (curproxy->cap & PR_CAP_FE)
3250 curproxy->options |= PR_O_TCP_CLI_KA;
3251 if (curproxy->cap & PR_CAP_BE)
3252 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 }
3254 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003255 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_WARN;
3257
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003259 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003260 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003261 curproxy->options2 &= ~PR_O2_CHK_ANY;
3262 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 if (!*args[2]) { /* no argument */
3264 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3265 curproxy->check_len = strlen(DEF_CHECK_REQ);
3266 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003267 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 curproxy->check_req = (char *)malloc(reqlen);
3269 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003270 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003272 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 if (*args[4])
3274 reqlen += strlen(args[4]);
3275 else
3276 reqlen += strlen("HTTP/1.0");
3277
3278 curproxy->check_req = (char *)malloc(reqlen);
3279 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003280 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003282 }
3283 else if (!strcmp(args[1], "ssl-hello-chk")) {
3284 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003285 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003286 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003287
Willy Tarreaua534fea2008-08-03 12:19:50 +02003288 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003289 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003290 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003291 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
Willy Tarreau23677902007-05-08 23:50:35 +02003293 else if (!strcmp(args[1], "smtpchk")) {
3294 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003295 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003296 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003297 curproxy->options2 &= ~PR_O2_CHK_ANY;
3298 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003299
3300 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3301 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3302 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3303 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3304 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3305 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3306 curproxy->check_req = (char *)malloc(reqlen);
3307 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3308 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3309 } else {
3310 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3311 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3312 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3313 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3314 }
3315 }
3316 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003317 else if (!strcmp(args[1], "pgsql-check")) {
3318 /* use PostgreSQL request to check servers' health */
3319 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3320 err_code |= ERR_WARN;
3321
3322 free(curproxy->check_req);
3323 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003324 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003325 curproxy->options2 |= PR_O2_PGSQL_CHK;
3326
3327 if (*(args[2])) {
3328 int cur_arg = 2;
3329
3330 while (*(args[cur_arg])) {
3331 if (strcmp(args[cur_arg], "user") == 0) {
3332 char * packet;
3333 uint32_t packet_len;
3334 uint32_t pv;
3335
3336 /* suboption header - needs additional argument for it */
3337 if (*(args[cur_arg+1]) == 0) {
3338 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3339 file, linenum, args[0], args[1], args[cur_arg]);
3340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
3342 }
3343
3344 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3345 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3346 pv = htonl(0x30000); /* protocol version 3.0 */
3347
3348 packet = (char*) calloc(1, packet_len);
3349
3350 memcpy(packet + 4, &pv, 4);
3351
3352 /* copy "user" */
3353 memcpy(packet + 8, "user", 4);
3354
3355 /* copy username */
3356 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3357
3358 free(curproxy->check_req);
3359 curproxy->check_req = packet;
3360 curproxy->check_len = packet_len;
3361
3362 packet_len = htonl(packet_len);
3363 memcpy(packet, &packet_len, 4);
3364 cur_arg += 2;
3365 } else {
3366 /* unknown suboption - catchall */
3367 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3368 file, linenum, args[0], args[1]);
3369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
3371 }
3372 } /* end while loop */
3373 }
3374 }
3375
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003376 else if (!strcmp(args[1], "redis-check")) {
3377 /* use REDIS PING request to check servers' health */
3378 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3379 err_code |= ERR_WARN;
3380
3381 free(curproxy->check_req);
3382 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003383 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003384 curproxy->options2 |= PR_O2_REDIS_CHK;
3385
3386 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3387 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3388 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3389 }
3390
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003391 else if (!strcmp(args[1], "mysql-check")) {
3392 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3394 err_code |= ERR_WARN;
3395
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003396 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003397 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003398 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003399 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003400
3401 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3402 * const char mysql40_client_auth_pkt[] = {
3403 * "\x0e\x00\x00" // packet length
3404 * "\x01" // packet number
3405 * "\x00\x00" // client capabilities
3406 * "\x00\x00\x01" // max packet
3407 * "haproxy\x00" // username (null terminated string)
3408 * "\x00" // filler (always 0x00)
3409 * "\x01\x00\x00" // packet length
3410 * "\x00" // packet number
3411 * "\x01" // COM_QUIT command
3412 * };
3413 */
3414
3415 if (*(args[2])) {
3416 int cur_arg = 2;
3417
3418 while (*(args[cur_arg])) {
3419 if (strcmp(args[cur_arg], "user") == 0) {
3420 char *mysqluser;
3421 int packetlen, reqlen, userlen;
3422
3423 /* suboption header - needs additional argument for it */
3424 if (*(args[cur_arg+1]) == 0) {
3425 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3426 file, linenum, args[0], args[1], args[cur_arg]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430 mysqluser = args[cur_arg + 1];
3431 userlen = strlen(mysqluser);
3432 packetlen = userlen + 7;
3433 reqlen = packetlen + 9;
3434
3435 free(curproxy->check_req);
3436 curproxy->check_req = (char *)calloc(1, reqlen);
3437 curproxy->check_len = reqlen;
3438
3439 snprintf(curproxy->check_req, 4, "%c%c%c",
3440 ((unsigned char) packetlen & 0xff),
3441 ((unsigned char) (packetlen >> 8) & 0xff),
3442 ((unsigned char) (packetlen >> 16) & 0xff));
3443
3444 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003445 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003446 curproxy->check_req[8] = 1;
3447 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3448 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3449 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3450 cur_arg += 2;
3451 } else {
3452 /* unknown suboption - catchall */
3453 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3454 file, linenum, args[0], args[1]);
3455 err_code |= ERR_ALERT | ERR_FATAL;
3456 goto out;
3457 }
3458 } /* end while loop */
3459 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003460 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003461 else if (!strcmp(args[1], "ldap-check")) {
3462 /* use LDAP request to check servers' health */
3463 free(curproxy->check_req);
3464 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003465 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003466 curproxy->options2 |= PR_O2_LDAP_CHK;
3467
3468 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3469 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3470 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3471 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003472 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003473 int cur_arg;
3474
3475 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3476 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003477 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003478
Willy Tarreau87cf5142011-08-19 22:57:24 +02003479 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003480
3481 free(curproxy->fwdfor_hdr_name);
3482 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3483 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3484
3485 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3486 cur_arg = 2;
3487 while (*(args[cur_arg])) {
3488 if (!strcmp(args[cur_arg], "except")) {
3489 /* suboption except - needs additional argument for it */
3490 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3491 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3492 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003495 }
3496 /* flush useless bits */
3497 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003498 cur_arg += 2;
3499 } else if (!strcmp(args[cur_arg], "header")) {
3500 /* suboption header - needs additional argument for it */
3501 if (*(args[cur_arg+1]) == 0) {
3502 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3503 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003506 }
3507 free(curproxy->fwdfor_hdr_name);
3508 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3509 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3510 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003511 } else if (!strcmp(args[cur_arg], "if-none")) {
3512 curproxy->options &= ~PR_O_FF_ALWAYS;
3513 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003514 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003515 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003516 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003517 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003518 err_code |= ERR_ALERT | ERR_FATAL;
3519 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003520 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003521 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003522 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003523 else if (!strcmp(args[1], "originalto")) {
3524 int cur_arg;
3525
3526 /* insert x-original-to field, but not for the IP address listed as an except.
3527 * set default options (ie: bitfield, header name, etc)
3528 */
3529
3530 curproxy->options |= PR_O_ORGTO;
3531
3532 free(curproxy->orgto_hdr_name);
3533 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3534 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3535
Willy Tarreau87cf5142011-08-19 22:57:24 +02003536 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003537 cur_arg = 2;
3538 while (*(args[cur_arg])) {
3539 if (!strcmp(args[cur_arg], "except")) {
3540 /* suboption except - needs additional argument for it */
3541 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3542 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3543 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003546 }
3547 /* flush useless bits */
3548 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3549 cur_arg += 2;
3550 } else if (!strcmp(args[cur_arg], "header")) {
3551 /* suboption header - needs additional argument for it */
3552 if (*(args[cur_arg+1]) == 0) {
3553 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3554 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003555 err_code |= ERR_ALERT | ERR_FATAL;
3556 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003557 }
3558 free(curproxy->orgto_hdr_name);
3559 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3560 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3561 cur_arg += 2;
3562 } else {
3563 /* unknown suboption - catchall */
3564 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3565 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003566 err_code |= ERR_ALERT | ERR_FATAL;
3567 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003568 }
3569 } /* end while loop */
3570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 else {
3572 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 }
Willy Tarreau93893792009-07-23 13:19:11 +02003576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003577 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003578 else if (!strcmp(args[0], "default_backend")) {
3579 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003581
3582 if (*(args[1]) == 0) {
3583 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003586 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003587 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003588 curproxy->defbe.name = strdup(args[1]);
3589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003590 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003591 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003592 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003593
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003594 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003596 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 /* enable reconnections to dispatch */
3598 curproxy->options |= PR_O_REDISP;
3599 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003600 else if (!strcmp(args[0], "http-check")) {
3601 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003603
3604 if (strcmp(args[1], "disable-on-404") == 0) {
3605 /* enable a graceful server shutdown on an HTTP 404 response */
3606 curproxy->options |= PR_O_DISABLE404;
3607 }
Willy Tarreauef781042010-01-27 11:53:01 +01003608 else if (strcmp(args[1], "send-state") == 0) {
3609 /* enable emission of the apparent state of a server in HTTP checks */
3610 curproxy->options2 |= PR_O2_CHK_SNDST;
3611 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003612 else if (strcmp(args[1], "expect") == 0) {
3613 const char *ptr_arg;
3614 int cur_arg;
3615
3616 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3617 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
3620 }
3621
3622 cur_arg = 2;
3623 /* consider exclamation marks, sole or at the beginning of a word */
3624 while (*(ptr_arg = args[cur_arg])) {
3625 while (*ptr_arg == '!') {
3626 curproxy->options2 ^= PR_O2_EXP_INV;
3627 ptr_arg++;
3628 }
3629 if (*ptr_arg)
3630 break;
3631 cur_arg++;
3632 }
3633 /* now ptr_arg points to the beginning of a word past any possible
3634 * exclamation mark, and cur_arg is the argument which holds this word.
3635 */
3636 if (strcmp(ptr_arg, "status") == 0) {
3637 if (!*(args[cur_arg + 1])) {
3638 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3639 file, linenum, args[0], args[1], ptr_arg);
3640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
3642 }
3643 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003644 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003645 curproxy->expect_str = strdup(args[cur_arg + 1]);
3646 }
3647 else if (strcmp(ptr_arg, "string") == 0) {
3648 if (!*(args[cur_arg + 1])) {
3649 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3650 file, linenum, args[0], args[1], ptr_arg);
3651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
3653 }
3654 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003655 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003656 curproxy->expect_str = strdup(args[cur_arg + 1]);
3657 }
3658 else if (strcmp(ptr_arg, "rstatus") == 0) {
3659 if (!*(args[cur_arg + 1])) {
3660 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3661 file, linenum, args[0], args[1], ptr_arg);
3662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
3664 }
3665 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003666 free(curproxy->expect_str);
3667 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3668 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003669 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3670 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3671 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3672 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676 }
3677 else if (strcmp(ptr_arg, "rstring") == 0) {
3678 if (!*(args[cur_arg + 1])) {
3679 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3680 file, linenum, args[0], args[1], ptr_arg);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
3684 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003685 free(curproxy->expect_str);
3686 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3687 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003688 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3689 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3690 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3691 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
3694 }
3695 }
3696 else {
3697 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3698 file, linenum, args[0], args[1], ptr_arg);
3699 err_code |= ERR_ALERT | ERR_FATAL;
3700 goto out;
3701 }
3702 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003703 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003704 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 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003707 }
3708 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003709 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003710 if (curproxy == &defproxy) {
3711 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003714 }
3715
Willy Tarreaub80c2302007-11-30 20:51:32 +01003716 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003718
3719 if (strcmp(args[1], "fail") == 0) {
3720 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003721 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003722 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3723 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003726 }
3727
Willy Tarreauef6494c2010-01-28 17:12:36 +01003728 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003729 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3730 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003733 }
3734 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3735 }
3736 else {
3737 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003740 }
3741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742#ifdef TPROXY
3743 else if (!strcmp(args[0], "transparent")) {
3744 /* enable transparent proxy connections */
3745 curproxy->options |= PR_O_TRANSP;
3746 }
3747#endif
3748 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003751
Willy Tarreaubaaee002006-06-26 02:48:02 +02003752 if (*(args[1]) == 0) {
3753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 }
3757 curproxy->maxconn = atol(args[1]);
3758 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003759 else if (!strcmp(args[0], "backlog")) { /* backlog */
3760 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003761 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003762
3763 if (*(args[1]) == 0) {
3764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003767 }
3768 curproxy->backlog = atol(args[1]);
3769 }
Willy Tarreau86034312006-12-29 00:10:33 +01003770 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003771 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003773
Willy Tarreau86034312006-12-29 00:10:33 +01003774 if (*(args[1]) == 0) {
3775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003778 }
3779 curproxy->fullconn = atol(args[1]);
3780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3782 if (*(args[1]) == 0) {
3783 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003787 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3788 if (err) {
3789 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3790 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003793 }
3794 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003795 }
3796 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003797 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003798 if (curproxy == &defproxy) {
3799 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003803 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003805
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 if (strchr(args[1], ':') == NULL) {
3807 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003808 err_code |= ERR_ALERT | ERR_FATAL;
3809 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003810 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003811 sk = str2sa(args[1]);
3812 if (!sk) {
3813 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
3816 }
3817 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003818 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003819 }
3820 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003821 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003823
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003824 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003825 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3826 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003829 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003831 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3832 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3833 err_code |= ERR_WARN;
3834
3835 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3836 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3837 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3838 }
3839 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3840 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3841 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3842 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003843 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3844 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3845 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3846 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003847 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003848 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003849 err_code |= ERR_ALERT | ERR_FATAL;
3850 goto out;
3851 }
3852 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003853 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003855 char *rport, *raddr;
3856 short realport = 0;
3857 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003859 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 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_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866
3867 if (!*args[2]) {
3868 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3869 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003873
3874 err = invalid_char(args[1]);
3875 if (err) {
3876 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3877 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003880 }
3881
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003882 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003883 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003884
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003885 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3886 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3887 err_code |= ERR_ALERT | ERR_ABORT;
3888 goto out;
3889 }
3890
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003891 /* the servers are linked backwards first */
3892 newsrv->next = curproxy->srv;
3893 curproxy->srv = newsrv;
3894 newsrv->proxy = curproxy;
3895 newsrv->conf.file = file;
3896 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897
Simon Hormanaf514952011-06-21 14:34:57 +09003898 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003899 LIST_INIT(&newsrv->pendconns);
3900 do_check = 0;
3901 newsrv->state = SRV_RUNNING; /* early server setup */
3902 newsrv->last_change = now.tv_sec;
3903 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003905 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003906 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003907 * - IP: => port=+0, relative
3908 * - IP:N => port=N, absolute
3909 * - IP:+N => port=+N, relative
3910 * - IP:-N => port=-N, relative
3911 */
3912 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003913 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003914 if (rport) {
3915 *rport++ = 0;
3916 realport = atol(rport);
3917 if (!isdigit((unsigned char)*rport))
3918 newsrv->state |= SRV_MAPPORTS;
3919 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003920 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003921
Willy Tarreaufab5a432011-03-04 15:31:53 +01003922 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003923 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003924 if (!sk) {
3925 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02003930 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003931
3932 newsrv->check_port = curproxy->defsrv.check_port;
3933 newsrv->inter = curproxy->defsrv.inter;
3934 newsrv->fastinter = curproxy->defsrv.fastinter;
3935 newsrv->downinter = curproxy->defsrv.downinter;
3936 newsrv->rise = curproxy->defsrv.rise;
3937 newsrv->fall = curproxy->defsrv.fall;
3938 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3939 newsrv->minconn = curproxy->defsrv.minconn;
3940 newsrv->maxconn = curproxy->defsrv.maxconn;
3941 newsrv->slowstart = curproxy->defsrv.slowstart;
3942 newsrv->onerror = curproxy->defsrv.onerror;
3943 newsrv->consecutive_errors_limit
3944 = curproxy->defsrv.consecutive_errors_limit;
3945 newsrv->uweight = newsrv->iweight
3946 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003948 newsrv->curfd = -1; /* no health-check in progress */
3949 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003951 cur_arg = 3;
3952 } else {
3953 newsrv = &curproxy->defsrv;
3954 cur_arg = 1;
3955 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003956
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003958 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003959 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003960
3961 if (!*args[cur_arg + 1]) {
3962 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3963 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003966 }
3967
3968 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003969 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003970
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003971 if (newsrv->puid <= 0) {
3972 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003973 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003976 }
3977
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003978 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
3979 if (node) {
3980 struct server *target = container_of(node, struct server, conf.id);
3981 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3982 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3983 err_code |= ERR_ALERT | ERR_FATAL;
3984 goto out;
3985 }
3986 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003987 cur_arg += 2;
3988 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003989 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003990 newsrv->cookie = strdup(args[cur_arg + 1]);
3991 newsrv->cklen = strlen(args[cur_arg + 1]);
3992 cur_arg += 2;
3993 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003994 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003995 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3996 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3997 cur_arg += 2;
3998 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004000 if (!*args[cur_arg + 1]) {
4001 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4002 file, linenum, args[cur_arg]);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
4005 }
4006
Willy Tarreaubaaee002006-06-26 02:48:02 +02004007 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004008 if (newsrv->rise <= 0) {
4009 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4010 file, linenum, args[cur_arg]);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
4014
Willy Tarreau96839092010-03-29 10:02:24 +02004015 if (newsrv->health)
4016 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 cur_arg += 2;
4018 }
4019 else if (!strcmp(args[cur_arg], "fall")) {
4020 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004021
4022 if (!*args[cur_arg + 1]) {
4023 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4024 file, linenum, args[cur_arg]);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028
4029 if (newsrv->fall <= 0) {
4030 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4031 file, linenum, args[cur_arg]);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
4035
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 cur_arg += 2;
4037 }
4038 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004039 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4040 if (err) {
4041 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4042 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004045 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004046 if (val <= 0) {
4047 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4048 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004049 err_code |= ERR_ALERT | ERR_FATAL;
4050 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004051 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004052 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 cur_arg += 2;
4054 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004055 else if (!strcmp(args[cur_arg], "fastinter")) {
4056 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4057 if (err) {
4058 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4059 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004062 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004063 if (val <= 0) {
4064 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4065 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004068 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004069 newsrv->fastinter = val;
4070 cur_arg += 2;
4071 }
4072 else if (!strcmp(args[cur_arg], "downinter")) {
4073 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4074 if (err) {
4075 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4076 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004079 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004080 if (val <= 0) {
4081 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4082 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004085 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004086 newsrv->downinter = val;
4087 cur_arg += 2;
4088 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004089 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004090 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004091 if (!sk) {
4092 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
4095 }
4096 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004097 cur_arg += 2;
4098 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 else if (!strcmp(args[cur_arg], "port")) {
4100 newsrv->check_port = atol(args[cur_arg + 1]);
4101 cur_arg += 2;
4102 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004103 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004104 newsrv->state |= SRV_BACKUP;
4105 cur_arg ++;
4106 }
Simon Hormanfa461682011-06-25 09:39:49 +09004107 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4108 newsrv->state |= SRV_NON_STICK;
4109 cur_arg ++;
4110 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004111 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4112 newsrv->state |= SRV_SEND_PROXY;
4113 cur_arg ++;
4114 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 else if (!strcmp(args[cur_arg], "weight")) {
4116 int w;
4117 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004118 if (w < 0 || w > 256) {
4119 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004120 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004123 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004124 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125 cur_arg += 2;
4126 }
4127 else if (!strcmp(args[cur_arg], "minconn")) {
4128 newsrv->minconn = atol(args[cur_arg + 1]);
4129 cur_arg += 2;
4130 }
4131 else if (!strcmp(args[cur_arg], "maxconn")) {
4132 newsrv->maxconn = atol(args[cur_arg + 1]);
4133 cur_arg += 2;
4134 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004135 else if (!strcmp(args[cur_arg], "maxqueue")) {
4136 newsrv->maxqueue = atol(args[cur_arg + 1]);
4137 cur_arg += 2;
4138 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004139 else if (!strcmp(args[cur_arg], "slowstart")) {
4140 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004141 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004142 if (err) {
4143 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4144 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004147 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004148 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004149 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4150 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004153 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004154 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004155 cur_arg += 2;
4156 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004157 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004158
4159 if (!*args[cur_arg + 1]) {
4160 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4161 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004164 }
4165
4166 newsrv->trackit = strdup(args[cur_arg + 1]);
4167
4168 cur_arg += 2;
4169 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004170 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004171 global.maxsock++;
4172 do_check = 1;
4173 cur_arg += 1;
4174 }
Willy Tarreau96839092010-03-29 10:02:24 +02004175 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4176 newsrv->state |= SRV_MAINTAIN;
4177 newsrv->state &= ~SRV_RUNNING;
4178 newsrv->health = 0;
4179 cur_arg += 1;
4180 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004181 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004182 if (!strcmp(args[cur_arg + 1], "none"))
4183 newsrv->observe = HANA_OBS_NONE;
4184 else if (!strcmp(args[cur_arg + 1], "layer4"))
4185 newsrv->observe = HANA_OBS_LAYER4;
4186 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4187 if (curproxy->mode != PR_MODE_HTTP) {
4188 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4189 file, linenum, args[cur_arg + 1]);
4190 err_code |= ERR_ALERT;
4191 }
4192 newsrv->observe = HANA_OBS_LAYER7;
4193 }
4194 else {
4195 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004196 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004197 file, linenum, args[cur_arg], args[cur_arg + 1]);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201
4202 cur_arg += 2;
4203 }
4204 else if (!strcmp(args[cur_arg], "on-error")) {
4205 if (!strcmp(args[cur_arg + 1], "fastinter"))
4206 newsrv->onerror = HANA_ONERR_FASTINTER;
4207 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4208 newsrv->onerror = HANA_ONERR_FAILCHK;
4209 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4210 newsrv->onerror = HANA_ONERR_SUDDTH;
4211 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4212 newsrv->onerror = HANA_ONERR_MARKDWN;
4213 else {
4214 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004215 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004216 file, linenum, args[cur_arg], args[cur_arg + 1]);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
4220
4221 cur_arg += 2;
4222 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004223 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4224 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4225 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4226 else {
4227 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4228 file, linenum, args[cur_arg], args[cur_arg + 1]);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
4231 }
4232
4233 cur_arg += 2;
4234 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004235 else if (!strcmp(args[cur_arg], "error-limit")) {
4236 if (!*args[cur_arg + 1]) {
4237 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4238 file, linenum, args[cur_arg]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
4241 }
4242
4243 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4244
4245 if (newsrv->consecutive_errors_limit <= 0) {
4246 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4247 file, linenum, args[cur_arg]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004251 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004252 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004253 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004254 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004255 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004256
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004258#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004259 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004260 file, linenum, "source", "usesrc");
4261#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004262 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004264#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 }
4268 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004269 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4270 if (!sk) {
4271 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004276
4277 if (port_low != port_high) {
4278 int i;
4279 if (port_low <= 0 || port_low > 65535 ||
4280 port_high <= 0 || port_high > 65535 ||
4281 port_low > port_high) {
4282 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4283 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004286 }
4287 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4288 for (i = 0; i < newsrv->sport_range->size; i++)
4289 newsrv->sport_range->ports[i] = port_low + i;
4290 }
4291
Willy Tarreaubaaee002006-06-26 02:48:02 +02004292 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004293 while (*(args[cur_arg])) {
4294 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004295#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4296#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004297 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4298 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4299 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004302 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004303#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004304 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004305 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004306 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_ALERT | ERR_FATAL;
4308 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004309 }
4310 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004311 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004312 newsrv->state |= SRV_TPROXY_CLI;
4313 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004314 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004315 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004316 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4317 char *name, *end;
4318
4319 name = args[cur_arg+1] + 7;
4320 while (isspace(*name))
4321 name++;
4322
4323 end = name;
4324 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4325 end++;
4326
4327 newsrv->state &= ~SRV_TPROXY_MASK;
4328 newsrv->state |= SRV_TPROXY_DYN;
4329 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4330 newsrv->bind_hdr_len = end - name;
4331 memcpy(newsrv->bind_hdr_name, name, end - name);
4332 newsrv->bind_hdr_name[end-name] = '\0';
4333 newsrv->bind_hdr_occ = -1;
4334
4335 /* now look for an occurrence number */
4336 while (isspace(*end))
4337 end++;
4338 if (*end == ',') {
4339 end++;
4340 name = end;
4341 if (*end == '-')
4342 end++;
4343 while (isdigit(*end))
4344 end++;
4345 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4346 }
4347
4348 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4349 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4350 " occurrences values smaller than %d.\n",
4351 file, linenum, MAX_HDR_HISTORY);
4352 err_code |= ERR_ALERT | ERR_FATAL;
4353 goto out;
4354 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004355 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004356 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004357 if (!sk) {
4358 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
4361 }
4362 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004363 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004364 }
4365 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004366#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004367 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004368#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004369 cur_arg += 2;
4370 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004371#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004372 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004373 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004376#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4377 } /* "usesrc" */
4378
4379 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4380#ifdef SO_BINDTODEVICE
4381 if (!*args[cur_arg + 1]) {
4382 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4383 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 }
4387 if (newsrv->iface_name)
4388 free(newsrv->iface_name);
4389
4390 newsrv->iface_name = strdup(args[cur_arg + 1]);
4391 newsrv->iface_len = strlen(newsrv->iface_name);
4392 global.last_checks |= LSTCHK_NETADM;
4393#else
4394 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4395 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004398#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004399 cur_arg += 2;
4400 continue;
4401 }
4402 /* this keyword in not an option of "source" */
4403 break;
4404 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004406 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004407 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4408 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004411 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004413 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004414 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 +01004415 file, linenum, newsrv->id);
4416 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004417 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 +01004418 file, linenum);
4419
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004422 }
4423 }
4424
4425 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004426 if (newsrv->trackit) {
4427 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4428 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004431 }
4432
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004433 /* try to get the port from check_addr if check_port not set */
4434 if (!newsrv->check_port)
4435 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004436
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4438 newsrv->check_port = realport; /* by default */
4439 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004440 /* not yet valid, because no port was set on
4441 * the server either. We'll check if we have
4442 * a known port on the first listener.
4443 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004444 struct listener *l = curproxy->listen;
4445 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4446 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004447 }
4448 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4450 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004454
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004455 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004456 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004457 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4458 err_code |= ERR_ALERT | ERR_ABORT;
4459 goto out;
4460 }
4461
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004462 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 newsrv->state |= SRV_CHECKED;
4464 }
4465
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004466 if (!defsrv) {
4467 if (newsrv->state & SRV_BACKUP)
4468 curproxy->srv_bck++;
4469 else
4470 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004471
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004472 newsrv->prev_state = newsrv->state;
4473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 }
4475 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004476 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004477 int facility;
4478
4479 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4480 curproxy->logfac1 = global.logfac1;
4481 curproxy->logsrv1 = global.logsrv1;
4482 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004483 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 curproxy->logfac2 = global.logfac2;
4485 curproxy->logsrv2 = global.logsrv2;
4486 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004487 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 }
4489 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004490 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491
4492 facility = get_log_facility(args[2]);
4493 if (facility < 0) {
4494 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4495 exit(1);
4496 }
4497
4498 level = 7; /* max syslog level = debug */
4499 if (*(args[3])) {
4500 level = get_log_level(args[3]);
4501 if (level < 0) {
4502 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4503 exit(1);
4504 }
4505 }
4506
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004507 minlvl = 0; /* limit syslog level to this level (emerg) */
4508 if (*(args[4])) {
4509 minlvl = get_log_level(args[4]);
4510 if (level < 0) {
4511 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4512 exit(1);
4513 }
4514 }
4515
Robert Tsai81ae1952007-12-05 10:47:29 +01004516 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004517 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004518 if (!sk) {
4519 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004520 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004521 err_code |= ERR_ALERT | ERR_FATAL;
4522 goto out;
4523 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004524 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004525 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004526 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004527 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004528 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004532 logsrv.addr = *sk;
4533 if (!get_host_port(&logsrv.addr))
4534 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004535 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004536
4537 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004538 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004539 curproxy->logfac1 = facility;
4540 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004541 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 }
4543 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004544 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 curproxy->logfac2 = facility;
4546 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004547 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548 }
4549 else {
4550 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004553 }
4554 }
4555 else {
4556 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4557 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004560 }
4561 }
4562 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004563 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004564 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004565
Willy Tarreau977b8e42006-12-29 14:19:17 +01004566 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004567 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004568
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004570 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4571 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004575
4576 /* we must first clear any optional default setting */
4577 curproxy->options &= ~PR_O_TPXY_MASK;
4578 free(curproxy->iface_name);
4579 curproxy->iface_name = NULL;
4580 curproxy->iface_len = 0;
4581
Willy Tarreaud5191e72010-02-09 20:50:45 +01004582 sk = str2sa(args[1]);
4583 if (!sk) {
4584 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004590
4591 cur_arg = 2;
4592 while (*(args[cur_arg])) {
4593 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004594#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4595#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004596 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4597 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4598 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004601 }
4602#endif
4603 if (!*args[cur_arg + 1]) {
4604 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4605 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004606 err_code |= ERR_ALERT | ERR_FATAL;
4607 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004608 }
4609
4610 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004611 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004612 curproxy->options |= PR_O_TPXY_CLI;
4613 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004614 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004615 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004616 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4617 char *name, *end;
4618
4619 name = args[cur_arg+1] + 7;
4620 while (isspace(*name))
4621 name++;
4622
4623 end = name;
4624 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4625 end++;
4626
4627 curproxy->options &= ~PR_O_TPXY_MASK;
4628 curproxy->options |= PR_O_TPXY_DYN;
4629 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4630 curproxy->bind_hdr_len = end - name;
4631 memcpy(curproxy->bind_hdr_name, name, end - name);
4632 curproxy->bind_hdr_name[end-name] = '\0';
4633 curproxy->bind_hdr_occ = -1;
4634
4635 /* now look for an occurrence number */
4636 while (isspace(*end))
4637 end++;
4638 if (*end == ',') {
4639 end++;
4640 name = end;
4641 if (*end == '-')
4642 end++;
4643 while (isdigit(*end))
4644 end++;
4645 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4646 }
4647
4648 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4649 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4650 " occurrences values smaller than %d.\n",
4651 file, linenum, MAX_HDR_HISTORY);
4652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
4654 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004655 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004656 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004657 if (!sk) {
4658 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
4661 }
4662 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004663 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004664 }
4665 global.last_checks |= LSTCHK_NETADM;
4666#if !defined(CONFIG_HAP_LINUX_TPROXY)
4667 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004668#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004669#else /* no TPROXY support */
4670 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004671 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004674#endif
4675 cur_arg += 2;
4676 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004677 }
4678
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004679 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4680#ifdef SO_BINDTODEVICE
4681 if (!*args[cur_arg + 1]) {
4682 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4683 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004684 err_code |= ERR_ALERT | ERR_FATAL;
4685 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004686 }
4687 if (curproxy->iface_name)
4688 free(curproxy->iface_name);
4689
4690 curproxy->iface_name = strdup(args[cur_arg + 1]);
4691 curproxy->iface_len = strlen(curproxy->iface_name);
4692 global.last_checks |= LSTCHK_NETADM;
4693#else
4694 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4695 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004696 err_code |= ERR_ALERT | ERR_FATAL;
4697 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004698#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699 cur_arg += 2;
4700 continue;
4701 }
4702 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4703 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_ALERT | ERR_FATAL;
4705 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004708 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4709 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4710 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004711 err_code |= ERR_ALERT | ERR_FATAL;
4712 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004715 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4717 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004721
4722 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4723 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004724 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004725 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 }
4728 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004729 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4730 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004731 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004732 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734 }
4735 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004736 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4737 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004738 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004739 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
4742 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004743 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4744 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004745 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004746 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
4749 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004750 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4751 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004752 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004753 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004754 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004755 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004756 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004757 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4758 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004759 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004760 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004761 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004762 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004763 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004764 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4765 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004766 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004767 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004768 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004769 }
4770 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004771 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4772 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004773 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004774 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004775 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004776 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004778 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004779 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4780 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004781 err_code |= ERR_ALERT | ERR_FATAL;
4782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004784
4785 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4786 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004787 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004788 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 }
4791 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004792 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4793 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004794 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004795 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004797 }
4798 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004799 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4800 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004801 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004802 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 }
4805 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004806 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4807 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004808 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004809 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004811 }
4812 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4814 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004815 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004816 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004818 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004819 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004820 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4821 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004822 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004823 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004824 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004825 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004827 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004828
Willy Tarreaubaaee002006-06-26 02:48:02 +02004829 if (curproxy == &defproxy) {
4830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004834 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004835 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004836
Willy Tarreaubaaee002006-06-26 02:48:02 +02004837 if (*(args[1]) == 0) {
4838 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004841 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004842
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004843 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4844 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4845 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4846 file, linenum, args[0]);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
4850 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4851 }
4852 else if (*args[2]) {
4853 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4854 file, linenum, args[0], args[2]);
4855 err_code |= ERR_ALERT | ERR_FATAL;
4856 goto out;
4857 }
4858
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004859 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004860 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004861 wl->s = strdup(args[1]);
4862 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004863 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004864 }
4865 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004866 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4868 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004872
Willy Tarreauade5ec42010-01-28 19:33:49 +01004873 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4874 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004875 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004876 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 }
4879 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004880 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4881 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004882 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004883 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 }
4886 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004887 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4888 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004889 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004890 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004892 }
4893 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004894 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004895 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 }
4900
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4902 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004903 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004906 }
4907 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004908 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4909 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004910 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004913 }
4914 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4916 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004917 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004918 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004919 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 }
4921 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004922 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004923
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 if (curproxy == &defproxy) {
4925 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004929 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004930 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 if (*(args[1]) == 0) {
4933 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", 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 }
4937
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004938 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4939 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4940 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4941 file, linenum, args[0]);
4942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
4944 }
4945 err_code |= warnif_cond_requires_req(cond, file, linenum);
4946 }
4947 else if (*args[2]) {
4948 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4949 file, linenum, args[0], args[2]);
4950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
4952 }
4953
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004954 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004955 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004956 wl->s = strdup(args[1]);
4957 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 }
4959 else if (!strcmp(args[0], "errorloc") ||
4960 !strcmp(args[0], "errorloc302") ||
4961 !strcmp(args[0], "errorloc303")) { /* error location */
4962 int errnum, errlen;
4963 char *err;
4964
Willy Tarreau977b8e42006-12-29 14:19:17 +01004965 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004967
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004969 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973
4974 errnum = atol(args[1]);
4975 if (!strcmp(args[0], "errorloc303")) {
4976 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4977 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4978 } else {
4979 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4980 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4981 }
4982
Willy Tarreau0f772532006-12-23 20:51:41 +01004983 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4984 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004985 chunk_destroy(&curproxy->errmsg[rc]);
4986 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004987 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004990
4991 if (rc >= HTTP_ERR_SIZE) {
4992 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4993 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 free(err);
4995 }
4996 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004997 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4998 int errnum, errlen, fd;
4999 char *err;
5000 struct stat stat;
5001
5002 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005003 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005004
5005 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005006 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005007 err_code |= ERR_ALERT | ERR_FATAL;
5008 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005009 }
5010
5011 fd = open(args[2], O_RDONLY);
5012 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5013 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5014 file, linenum, args[2], args[1]);
5015 if (fd >= 0)
5016 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005019 }
5020
Willy Tarreau27a674e2009-08-17 07:23:33 +02005021 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005022 errlen = stat.st_size;
5023 } else {
5024 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005025 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005027 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005028 }
5029
5030 err = malloc(errlen); /* malloc() must succeed during parsing */
5031 errnum = read(fd, err, errlen);
5032 if (errnum != errlen) {
5033 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5034 file, linenum, args[2], args[1]);
5035 close(fd);
5036 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005037 err_code |= ERR_ALERT | ERR_FATAL;
5038 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005039 }
5040 close(fd);
5041
5042 errnum = atol(args[1]);
5043 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5044 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005045 chunk_destroy(&curproxy->errmsg[rc]);
5046 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005047 break;
5048 }
5049 }
5050
5051 if (rc >= HTTP_ERR_SIZE) {
5052 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5053 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005054 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005055 free(err);
5056 }
5057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005058 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005059 struct cfg_kw_list *kwl;
5060 int index;
5061
5062 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5063 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5064 if (kwl->kw[index].section != CFG_LISTEN)
5065 continue;
5066 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5067 /* prepare error message just in case */
5068 snprintf(trash, sizeof(trash),
5069 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005070 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5071 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005072 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005075 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005076 else if (rc > 0) {
5077 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005078 err_code |= ERR_WARN;
5079 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005080 }
Willy Tarreau93893792009-07-23 13:19:11 +02005081 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005082 }
5083 }
5084 }
5085
Willy Tarreau6daf3432008-01-22 16:44:08 +01005086 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005089 }
Willy Tarreau93893792009-07-23 13:19:11 +02005090 out:
5091 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092}
5093
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005094int
5095cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5096{
5097
5098 int err_code = 0;
5099 const char *err;
5100
5101 if (!strcmp(args[0], "userlist")) { /* new userlist */
5102 struct userlist *newul;
5103
5104 if (!*args[1]) {
5105 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5106 file, linenum, args[0]);
5107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
5110
5111 err = invalid_char(args[1]);
5112 if (err) {
5113 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5114 file, linenum, *err, args[0], args[1]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118
5119 for (newul = userlist; newul; newul = newul->next)
5120 if (!strcmp(newul->name, args[1])) {
5121 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5122 file, linenum, args[1]);
5123 err_code |= ERR_WARN;
5124 goto out;
5125 }
5126
5127 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5128 if (!newul) {
5129 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5130 err_code |= ERR_ALERT | ERR_ABORT;
5131 goto out;
5132 }
5133
5134 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5135 newul->name = strdup(args[1]);
5136
5137 if (!newul->groupusers | !newul->name) {
5138 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5139 err_code |= ERR_ALERT | ERR_ABORT;
5140 goto out;
5141 }
5142
5143 newul->next = userlist;
5144 userlist = newul;
5145
5146 } else if (!strcmp(args[0], "group")) { /* new group */
5147 int cur_arg, i;
5148 const char *err;
5149
5150 if (!*args[1]) {
5151 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5152 file, linenum, args[0]);
5153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
5155 }
5156
5157 err = invalid_char(args[1]);
5158 if (err) {
5159 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5160 file, linenum, *err, args[0], args[1]);
5161 err_code |= ERR_ALERT | ERR_FATAL;
5162 goto out;
5163 }
5164
5165 for(i = 0; i < userlist->grpcnt; i++)
5166 if (!strcmp(userlist->groups[i], args[1])) {
5167 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5168 file, linenum, args[1], userlist->name);
5169 err_code |= ERR_ALERT;
5170 goto out;
5171 }
5172
5173 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5174 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5175 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
5178 }
5179
5180 cur_arg = 2;
5181
5182 while (*args[cur_arg]) {
5183 if (!strcmp(args[cur_arg], "users")) {
5184 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5185 cur_arg += 2;
5186 continue;
5187 } else {
5188 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5189 file, linenum, args[0]);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193 }
5194
5195 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5196 } else if (!strcmp(args[0], "user")) { /* new user */
5197 struct auth_users *newuser;
5198 int cur_arg;
5199
5200 if (!*args[1]) {
5201 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5202 file, linenum, args[0]);
5203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206
5207 for (newuser = userlist->users; newuser; newuser = newuser->next)
5208 if (!strcmp(newuser->user, args[1])) {
5209 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5210 file, linenum, args[1], userlist->name);
5211 err_code |= ERR_ALERT;
5212 goto out;
5213 }
5214
5215 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5216 if (!newuser) {
5217 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5218 err_code |= ERR_ALERT | ERR_ABORT;
5219 goto out;
5220 }
5221
5222 newuser->user = strdup(args[1]);
5223
5224 newuser->next = userlist->users;
5225 userlist->users = newuser;
5226
5227 cur_arg = 2;
5228
5229 while (*args[cur_arg]) {
5230 if (!strcmp(args[cur_arg], "password")) {
5231#ifndef CONFIG_HAP_CRYPT
5232 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5233 file, linenum);
5234 err_code |= ERR_ALERT;
5235#endif
5236 newuser->pass = strdup(args[cur_arg + 1]);
5237 cur_arg += 2;
5238 continue;
5239 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5240 newuser->pass = strdup(args[cur_arg + 1]);
5241 newuser->flags |= AU_O_INSECURE;
5242 cur_arg += 2;
5243 continue;
5244 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005245 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005246 cur_arg += 2;
5247 continue;
5248 } else {
5249 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5250 file, linenum, args[0]);
5251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
5253 }
5254 }
5255 } else {
5256 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5257 err_code |= ERR_ALERT | ERR_FATAL;
5258 }
5259
5260out:
5261 return err_code;
5262}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263
5264/*
5265 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005266 * Returns the error code, 0 if OK, or any combination of :
5267 * - ERR_ABORT: must abort ASAP
5268 * - ERR_FATAL: we can continue parsing but not start the service
5269 * - ERR_WARN: a warning has been emitted
5270 * - ERR_ALERT: an alert has been emitted
5271 * Only the two first ones can stop processing, the two others are just
5272 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005274int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005276 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 FILE *f;
5278 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005279 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005280 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 if ((f=fopen(file,"r")) == NULL)
5283 return -1;
5284
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005285 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005286 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005287 char *end;
5288 char *args[MAX_LINE_ARGS + 1];
5289 char *line = thisline;
5290
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 linenum++;
5292
5293 end = line + strlen(line);
5294
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005295 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5296 /* Check if we reached the limit and the last char is not \n.
5297 * Watch out for the last line without the terminating '\n'!
5298 */
5299 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005300 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005301 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005302 }
5303
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005305 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 line++;
5307
5308 arg = 0;
5309 args[arg] = line;
5310
5311 while (*line && arg < MAX_LINE_ARGS) {
5312 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5313 * C equivalent value. Other combinations left unchanged (eg: \1).
5314 */
5315 if (*line == '\\') {
5316 int skip = 0;
5317 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5318 *line = line[1];
5319 skip = 1;
5320 }
5321 else if (line[1] == 'r') {
5322 *line = '\r';
5323 skip = 1;
5324 }
5325 else if (line[1] == 'n') {
5326 *line = '\n';
5327 skip = 1;
5328 }
5329 else if (line[1] == 't') {
5330 *line = '\t';
5331 skip = 1;
5332 }
5333 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005334 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 unsigned char hex1, hex2;
5336 hex1 = toupper(line[2]) - '0';
5337 hex2 = toupper(line[3]) - '0';
5338 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5339 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5340 *line = (hex1<<4) + hex2;
5341 skip = 3;
5342 }
5343 else {
5344 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 }
5347 }
5348 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005349 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005350 end -= skip;
5351 }
5352 line++;
5353 }
5354 else if (*line == '#' || *line == '\n' || *line == '\r') {
5355 /* end of string, end of loop */
5356 *line = 0;
5357 break;
5358 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005359 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005361 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005362 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 line++;
5364 args[++arg] = line;
5365 }
5366 else {
5367 line++;
5368 }
5369 }
5370
5371 /* empty line */
5372 if (!**args)
5373 continue;
5374
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005375 if (*line) {
5376 /* we had to stop due to too many args.
5377 * Let's terminate the string, print the offending part then cut the
5378 * last arg.
5379 */
5380 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5381 line++;
5382 *line = '\0';
5383
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005384 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005385 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005386 err_code |= ERR_ALERT | ERR_FATAL;
5387 args[arg] = line;
5388 }
5389
Willy Tarreau540abe42007-05-02 20:50:16 +02005390 /* zero out remaining args and ensure that at least one entry
5391 * is zeroed out.
5392 */
5393 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005394 args[arg] = line;
5395 }
5396
Willy Tarreau3842f002009-06-14 11:39:52 +02005397 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005398 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005399 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005400 for (arg=0; *args[arg+1]; arg++)
5401 args[arg] = args[arg+1]; // shift args after inversion
5402 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005403 else if (!strcmp(args[0], "default")) {
5404 kwm = KWM_DEF;
5405 for (arg=0; *args[arg+1]; arg++)
5406 args[arg] = args[arg+1]; // shift args after inversion
5407 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005408
Willy Tarreau3842f002009-06-14 11:39:52 +02005409 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5410 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005411 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005412 }
5413
Willy Tarreau977b8e42006-12-29 14:19:17 +01005414 if (!strcmp(args[0], "listen") ||
5415 !strcmp(args[0], "frontend") ||
5416 !strcmp(args[0], "backend") ||
5417 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005418 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005420 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005421 cursection = strdup(args[0]);
5422 }
5423 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005425 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005426 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005427 }
5428 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005429 confsect = CFG_USERLIST;
5430 free(cursection);
5431 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005432 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005433 else if (!strcmp(args[0], "peers")) {
5434 confsect = CFG_PEERS;
5435 free(cursection);
5436 cursection = strdup(args[0]);
5437 }
5438
Willy Tarreaubaaee002006-06-26 02:48:02 +02005439 /* else it's a section keyword */
5440
5441 switch (confsect) {
5442 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005443 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005444 break;
5445 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005446 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005447 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005448 case CFG_USERLIST:
5449 err_code |= cfg_parse_users(file, linenum, args, kwm);
5450 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005451 case CFG_PEERS:
5452 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5453 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005455 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005456 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005458
5459 if (err_code & ERR_ABORT)
5460 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005462 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005463 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005465 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005466}
5467
Willy Tarreaubb925012009-07-23 13:36:36 +02005468/*
5469 * Returns the error code, 0 if OK, or any combination of :
5470 * - ERR_ABORT: must abort ASAP
5471 * - ERR_FATAL: we can continue parsing but not start the service
5472 * - ERR_WARN: a warning has been emitted
5473 * - ERR_ALERT: an alert has been emitted
5474 * Only the two first ones can stop processing, the two others are just
5475 * indicators.
5476 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005477int check_config_validity()
5478{
5479 int cfgerr = 0;
5480 struct proxy *curproxy = NULL;
5481 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005482 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005483 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005484 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485
5486 /*
5487 * Now, check for the integrity of all that we have collected.
5488 */
5489
5490 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005491 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005493 /* first, we will invert the proxy list order */
5494 curproxy = NULL;
5495 while (proxy) {
5496 struct proxy *next;
5497
5498 next = proxy->next;
5499 proxy->next = curproxy;
5500 curproxy = proxy;
5501 if (!next)
5502 break;
5503 proxy = next;
5504 }
5505
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005507 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
5511
5512 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005513 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005514 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005515 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005516 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005517 unsigned int next_id;
5518
5519 if (!curproxy->uuid) {
5520 /* proxy ID not set, use automatic numbering with first
5521 * spare entry starting with next_pxid.
5522 */
5523 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5524 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5525 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005526 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005527 next_pxid++;
5528
Willy Tarreau55ea7572007-06-17 19:56:27 +02005529
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005531 /* ensure we don't keep listeners uselessly bound */
5532 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005533 curproxy = curproxy->next;
5534 continue;
5535 }
5536
Willy Tarreauff01a212009-03-15 13:46:16 +01005537 switch (curproxy->mode) {
5538 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005539 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005540 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005541 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5542 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005543 cfgerr++;
5544 }
5545
5546 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005547 Warning("config : servers will be ignored for %s '%s'.\n",
5548 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005549 break;
5550
5551 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005552 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005553 break;
5554
5555 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005556 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005557 break;
5558 }
5559
5560 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005561 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5562 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 cfgerr++;
5564 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005565
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005566 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005567 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005568 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005569 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005571 cfgerr++;
5572 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005573#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005574 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005575 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5576 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005577 cfgerr++;
5578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005580 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005581 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5582 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005583 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005584 }
5585 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005586 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005587 /* If no LB algo is set in a backend, and we're not in
5588 * transparent mode, dispatch mode nor proxy mode, we
5589 * want to use balance roundrobin by default.
5590 */
5591 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5592 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 }
5594 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005595
Willy Tarreau1620ec32011-08-06 17:05:02 +02005596 if (curproxy->options & PR_O_DISPATCH)
5597 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5598 else if (curproxy->options & PR_O_HTTP_PROXY)
5599 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5600 else if (curproxy->options & PR_O_TRANSP)
5601 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005602
Willy Tarreau1620ec32011-08-06 17:05:02 +02005603 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5604 if (curproxy->options & PR_O_DISABLE404) {
5605 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5606 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5607 err_code |= ERR_WARN;
5608 curproxy->options &= ~PR_O_DISABLE404;
5609 }
5610 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5611 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5612 "send-state", proxy_type_str(curproxy), curproxy->id);
5613 err_code |= ERR_WARN;
5614 curproxy->options &= ~PR_O2_CHK_SNDST;
5615 }
Willy Tarreauef781042010-01-27 11:53:01 +01005616 }
5617
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005618 /* if a default backend was specified, let's find it */
5619 if (curproxy->defbe.name) {
5620 struct proxy *target;
5621
Alex Williams96532db2009-11-01 21:27:13 -05005622 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005623 if (!target) {
5624 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5625 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005626 cfgerr++;
5627 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005628 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5629 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005630 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005631 } else {
5632 free(curproxy->defbe.name);
5633 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005634 /* we force the backend to be present on at least all of
5635 * the frontend's processes.
5636 */
5637 target->bind_proc = curproxy->bind_proc ?
5638 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 }
5640 }
5641
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005642 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005643 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5644 /* map jump target for ACT_SETBE in req_rep chain */
5645 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005646 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005647 struct proxy *target;
5648
Willy Tarreaua496b602006-12-17 23:15:24 +01005649 if (exp->action != ACT_SETBE)
5650 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005651
Alex Williams96532db2009-11-01 21:27:13 -05005652 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005653 if (!target) {
5654 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5655 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005656 cfgerr++;
5657 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005658 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5659 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005660 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005661 } else {
5662 free((void *)exp->replace);
5663 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005664 /* we force the backend to be present on at least all of
5665 * the frontend's processes.
5666 */
5667 target->bind_proc = curproxy->bind_proc ?
5668 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005669 }
5670 }
5671 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005672
5673 /* find the target proxy for 'use_backend' rules */
5674 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005675 struct proxy *target;
5676
Alex Williams96532db2009-11-01 21:27:13 -05005677 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005678
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005679 if (!target) {
5680 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5681 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005682 cfgerr++;
5683 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005684 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5685 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005686 cfgerr++;
5687 } else {
5688 free((void *)rule->be.name);
5689 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005690 /* we force the backend to be present on at least all of
5691 * the frontend's processes.
5692 */
5693 target->bind_proc = curproxy->bind_proc ?
5694 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005695 }
5696 }
5697
Emeric Brunb982a3d2010-01-04 15:45:53 +01005698 /* find the target table for 'stick' rules */
5699 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5700 struct proxy *target;
5701
Emeric Brun1d33b292010-01-04 15:47:17 +01005702 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5703 if (mrule->flags & STK_IS_STORE)
5704 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5705
Emeric Brunb982a3d2010-01-04 15:45:53 +01005706 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005707 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005708 else
5709 target = curproxy;
5710
5711 if (!target) {
5712 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5713 curproxy->id, mrule->table.name);
5714 cfgerr++;
5715 }
5716 else if (target->table.size == 0) {
5717 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5718 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5719 cfgerr++;
5720 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005721 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005722 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5723 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5724 cfgerr++;
5725 }
5726 else {
5727 free((void *)mrule->table.name);
5728 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005729 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005730 }
5731 }
5732
5733 /* find the target table for 'store response' rules */
5734 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5735 struct proxy *target;
5736
Emeric Brun1d33b292010-01-04 15:47:17 +01005737 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5738
Emeric Brunb982a3d2010-01-04 15:45:53 +01005739 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005740 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005741 else
5742 target = curproxy;
5743
5744 if (!target) {
5745 Alert("Proxy '%s': unable to find store table '%s'.\n",
5746 curproxy->id, mrule->table.name);
5747 cfgerr++;
5748 }
5749 else if (target->table.size == 0) {
5750 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5751 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5752 cfgerr++;
5753 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005754 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005755 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5756 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5757 cfgerr++;
5758 }
5759 else {
5760 free((void *)mrule->table.name);
5761 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005762 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005763 }
5764 }
5765
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005766 /* find the target table for 'tcp-request' layer 4 rules */
5767 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5768 struct proxy *target;
5769
Willy Tarreau56123282010-08-06 19:06:56 +02005770 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005771 continue;
5772
5773 if (trule->act_prm.trk_ctr.table.n)
5774 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5775 else
5776 target = curproxy;
5777
5778 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005779 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5780 curproxy->id, trule->act_prm.trk_ctr.table.n,
5781 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005782 cfgerr++;
5783 }
5784 else if (target->table.size == 0) {
5785 Alert("Proxy '%s': table '%s' used but not configured.\n",
5786 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5787 cfgerr++;
5788 }
5789 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005790 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 +02005791 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5792 cfgerr++;
5793 }
5794 else {
5795 free(trule->act_prm.trk_ctr.table.n);
5796 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005797 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005798 * to pass a list of counters to track and allocate them right here using
5799 * stktable_alloc_data_type().
5800 */
5801 }
5802 }
5803
Willy Tarreaud1f96522010-08-03 19:34:32 +02005804 /* find the target table for 'tcp-request' layer 6 rules */
5805 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5806 struct proxy *target;
5807
Willy Tarreau56123282010-08-06 19:06:56 +02005808 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005809 continue;
5810
5811 if (trule->act_prm.trk_ctr.table.n)
5812 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5813 else
5814 target = curproxy;
5815
5816 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005817 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5818 curproxy->id, trule->act_prm.trk_ctr.table.n,
5819 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005820 cfgerr++;
5821 }
5822 else if (target->table.size == 0) {
5823 Alert("Proxy '%s': table '%s' used but not configured.\n",
5824 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5825 cfgerr++;
5826 }
5827 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005828 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 +02005829 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5830 cfgerr++;
5831 }
5832 else {
5833 free(trule->act_prm.trk_ctr.table.n);
5834 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005835 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005836 * to pass a list of counters to track and allocate them right here using
5837 * stktable_alloc_data_type().
5838 */
5839 }
5840 }
5841
Emeric Brun32da3c42010-09-23 18:39:19 +02005842 if (curproxy->table.peers.name) {
5843 struct peers *curpeers = peers;
5844
5845 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5846 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5847 free((void *)curproxy->table.peers.name);
5848 curproxy->table.peers.p = peers;
5849 break;
5850 }
5851 }
5852
5853 if (!curpeers) {
5854 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5855 curproxy->id, curproxy->table.peers.name);
5856 cfgerr++;
5857 }
5858 else if (!curpeers->peers_fe) {
5859 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5860 curproxy->id, curpeers->id);
5861 cfgerr++;
5862 }
5863 }
5864
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005865 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005866 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005867 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5868 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5869 "proxy", curproxy->id);
5870 cfgerr++;
5871 goto out_uri_auth_compat;
5872 }
5873
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005874 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005875 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005876 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005877 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005878
Willy Tarreau95fa4692010-02-01 13:05:50 +01005879 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5880 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005881
5882 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005883 uri_auth_compat_req[i++] = "realm";
5884 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5885 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005886
Willy Tarreau95fa4692010-02-01 13:05:50 +01005887 uri_auth_compat_req[i++] = "unless";
5888 uri_auth_compat_req[i++] = "{";
5889 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5890 uri_auth_compat_req[i++] = "}";
5891 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005892
Willy Tarreauff011f22011-01-06 17:51:27 +01005893 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5894 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005895 cfgerr++;
5896 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005897 }
5898
Willy Tarreauff011f22011-01-06 17:51:27 +01005899 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005900
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005901 if (curproxy->uri_auth->auth_realm) {
5902 free(curproxy->uri_auth->auth_realm);
5903 curproxy->uri_auth->auth_realm = NULL;
5904 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005905
5906 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005907 }
5908out_uri_auth_compat:
5909
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005910 cfgerr += acl_find_targets(curproxy);
5911
Willy Tarreau2738a142006-07-08 17:28:09 +02005912 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005913 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005914 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005915 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005916 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005917 " | While not properly invalid, you will certainly encounter various problems\n"
5918 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005919 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005920 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005921 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005922 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005923
Willy Tarreau1fa31262007-12-03 00:36:16 +01005924 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5925 * We must still support older configurations, so let's find out whether those
5926 * parameters have been set or must be copied from contimeouts.
5927 */
5928 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005929 if (!curproxy->timeout.tarpit ||
5930 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005931 /* tarpit timeout not set. We search in the following order:
5932 * default.tarpit, curr.connect, default.connect.
5933 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005934 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005935 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005936 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005937 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005938 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005939 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005940 }
5941 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005942 (!curproxy->timeout.queue ||
5943 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005944 /* queue timeout not set. We search in the following order:
5945 * default.queue, curr.connect, default.connect.
5946 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005947 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005948 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005949 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005950 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005951 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005952 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005953 }
5954 }
5955
Willy Tarreau1620ec32011-08-06 17:05:02 +02005956 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005957 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5958 curproxy->check_req = (char *)malloc(curproxy->check_len);
5959 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02005960 }
5961
Willy Tarreaucf7f3202007-05-13 22:46:04 +02005962 /* The small pools required for the capture lists */
5963 if (curproxy->nb_req_cap)
5964 curproxy->req_cap_pool = create_pool("ptrcap",
5965 curproxy->nb_req_cap * sizeof(char *),
5966 MEM_F_SHARED);
5967 if (curproxy->nb_rsp_cap)
5968 curproxy->rsp_cap_pool = create_pool("ptrcap",
5969 curproxy->nb_rsp_cap * sizeof(char *),
5970 MEM_F_SHARED);
5971
Willy Tarreau1d4154a2007-05-13 22:57:02 +02005972 curproxy->hdr_idx_pool = create_pool("hdr_idx",
5973 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
5974 MEM_F_SHARED);
5975
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976 /* first, we will invert the servers list order */
5977 newsrv = NULL;
5978 while (curproxy->srv) {
5979 struct server *next;
5980
5981 next = curproxy->srv->next;
5982 curproxy->srv->next = newsrv;
5983 newsrv = curproxy->srv;
5984 if (!next)
5985 break;
5986 curproxy->srv = next;
5987 }
5988
Willy Tarreaudd701652010-05-25 23:03:02 +02005989 /* assign automatic UIDs to servers which don't have one yet */
5990 next_id = 1;
5991 newsrv = curproxy->srv;
5992 while (newsrv != NULL) {
5993 if (!newsrv->puid) {
5994 /* server ID not set, use automatic numbering with first
5995 * spare entry starting with next_svid.
5996 */
5997 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
5998 newsrv->conf.id.key = newsrv->puid = next_id;
5999 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6000 }
6001 next_id++;
6002 newsrv = newsrv->next;
6003 }
6004
Willy Tarreau20697042007-11-15 23:26:18 +01006005 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006006 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006007
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006008 /* We have to initialize the server lookup mechanism depending
6009 * on what LB algorithm was choosen.
6010 */
6011
6012 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6013 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6014 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006015 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6016 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6017 init_server_map(curproxy);
6018 } else {
6019 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6020 fwrr_init_server_groups(curproxy);
6021 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006022 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006023
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006024 case BE_LB_KIND_LC:
6025 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006026 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006027 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006028
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006029 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006030 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6031 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6032 chash_init_server_tree(curproxy);
6033 } else {
6034 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6035 init_server_map(curproxy);
6036 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006037 break;
6038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039
6040 if (curproxy->options & PR_O_LOGASAP)
6041 curproxy->to_log &= ~LW_BYTES;
6042
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006043 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6044 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6045 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6046 proxy_type_str(curproxy), curproxy->id);
6047 err_code |= ERR_WARN;
6048 }
6049
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006050 if (curproxy->mode != PR_MODE_HTTP) {
6051 int optnum;
6052
6053 if (curproxy->options & PR_O_COOK_ANY) {
6054 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6055 proxy_type_str(curproxy), curproxy->id);
6056 err_code |= ERR_WARN;
6057 }
6058
6059 if (curproxy->uri_auth) {
6060 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6061 proxy_type_str(curproxy), curproxy->id);
6062 err_code |= ERR_WARN;
6063 curproxy->uri_auth = NULL;
6064 }
6065
Willy Tarreau87cf5142011-08-19 22:57:24 +02006066 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006067 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6068 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6069 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006070 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006071 }
6072
6073 if (curproxy->options & PR_O_ORGTO) {
6074 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6075 "originalto", proxy_type_str(curproxy), curproxy->id);
6076 err_code |= ERR_WARN;
6077 curproxy->options &= ~PR_O_ORGTO;
6078 }
6079
6080 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6081 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6082 (curproxy->cap & cfg_opts[optnum].cap) &&
6083 (curproxy->options & cfg_opts[optnum].val)) {
6084 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6085 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6086 err_code |= ERR_WARN;
6087 curproxy->options &= ~cfg_opts[optnum].val;
6088 }
6089 }
6090
6091 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6092 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6093 (curproxy->cap & cfg_opts2[optnum].cap) &&
6094 (curproxy->options2 & cfg_opts2[optnum].val)) {
6095 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6096 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6097 err_code |= ERR_WARN;
6098 curproxy->options2 &= ~cfg_opts2[optnum].val;
6099 }
6100 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006101
Willy Tarreauefa5f512010-03-30 20:13:29 +02006102#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006103 if (curproxy->bind_hdr_occ) {
6104 curproxy->bind_hdr_occ = 0;
6105 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6106 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6107 err_code |= ERR_WARN;
6108 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006109#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006110 }
6111
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006113 * ensure that we're not cross-dressing a TCP server into HTTP.
6114 */
6115 newsrv = curproxy->srv;
6116 while (newsrv != NULL) {
6117 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006118 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6119 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006120 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006121 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006122
Willy Tarreauefa5f512010-03-30 20:13:29 +02006123#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006124 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6125 newsrv->bind_hdr_occ = 0;
6126 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6127 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6128 err_code |= ERR_WARN;
6129 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006130#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006131 newsrv = newsrv->next;
6132 }
6133
6134 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 * If this server supports a maxconn parameter, it needs a dedicated
6136 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006137 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006138 */
6139 newsrv = curproxy->srv;
6140 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006141 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142 /* Only 'minconn' was specified, or it was higher than or equal
6143 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6144 * this will avoid further useless expensive computations.
6145 */
6146 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006147 } else if (newsrv->maxconn && !newsrv->minconn) {
6148 /* minconn was not specified, so we set it to maxconn */
6149 newsrv->minconn = newsrv->maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150 }
6151
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006152 if (newsrv->trackit) {
6153 struct proxy *px;
6154 struct server *srv;
6155 char *pname, *sname;
6156
6157 pname = newsrv->trackit;
6158 sname = strrchr(pname, '/');
6159
6160 if (sname)
6161 *sname++ = '\0';
6162 else {
6163 sname = pname;
6164 pname = NULL;
6165 }
6166
6167 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006168 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006169 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006170 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6171 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006172 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006173 cfgerr++;
6174 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006175 }
6176 } else
6177 px = curproxy;
6178
6179 srv = findserver(px, sname);
6180 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006181 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6182 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006183 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006184 cfgerr++;
6185 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006186 }
6187
6188 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006189 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006190 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006191 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006192 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006193 cfgerr++;
6194 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006195 }
6196
6197 if (curproxy != px &&
6198 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006199 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006200 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006201 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006202 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006203 cfgerr++;
6204 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006205 }
6206
6207 newsrv->tracked = srv;
6208 newsrv->tracknext = srv->tracknext;
6209 srv->tracknext = newsrv;
6210
6211 free(newsrv->trackit);
6212 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006213 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 newsrv = newsrv->next;
6215 }
6216
Willy Tarreauc1a21672009-08-16 22:37:44 +02006217 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006218 curproxy->accept = frontend_accept;
6219
Willy Tarreauc1a21672009-08-16 22:37:44 +02006220 if (curproxy->tcp_req.inspect_delay ||
6221 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006222 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006223
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006224 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006225 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006226 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006227 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006228
6229 /* both TCP and HTTP must check switching rules */
6230 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6231 }
6232
6233 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006234 if (curproxy->tcp_req.inspect_delay ||
6235 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6236 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6237
Emeric Brun97679e72010-09-23 17:56:44 +02006238 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6239 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6240
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006241 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006242 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006243 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006244 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006245
6246 /* If the backend does requires RDP cookie persistence, we have to
6247 * enable the corresponding analyser.
6248 */
6249 if (curproxy->options2 & PR_O2_RDPC_PRST)
6250 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6251 }
6252
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006253 listener = NULL;
6254 while (curproxy->listen) {
6255 struct listener *next;
6256
6257 next = curproxy->listen->next;
6258 curproxy->listen->next = listener;
6259 listener = curproxy->listen;
6260
6261 if (!next)
6262 break;
6263
6264 curproxy->listen = next;
6265 }
6266
Willy Tarreaue6b98942007-10-29 01:09:36 +01006267 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006268 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006269 listener = curproxy->listen;
6270 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006271 if (!listener->luid) {
6272 /* listener ID not set, use automatic numbering with first
6273 * spare entry starting with next_luid.
6274 */
6275 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6276 listener->conf.id.key = listener->luid = next_id;
6277 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006278 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006279 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006280
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006281 /* enable separate counters */
6282 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6283 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6284 if (!listener->name) {
6285 sprintf(trash, "sock-%d", listener->luid);
6286 listener->name = strdup(trash);
6287 }
6288 }
6289
Willy Tarreaue6b98942007-10-29 01:09:36 +01006290 if (curproxy->options & PR_O_TCP_NOLING)
6291 listener->options |= LI_O_NOLINGER;
6292 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006293 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006294 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006295 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006296 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006297 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006298 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006299
Willy Tarreau8a956912010-10-15 14:27:08 +02006300 if (listener->options & LI_O_ACC_PROXY)
6301 listener->analysers |= AN_REQ_DECODE_PROXY;
6302
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006303 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6304 listener->options |= LI_O_TCP_RULES;
6305
Willy Tarreaude3041d2010-05-31 10:56:17 +02006306 if (curproxy->mon_mask.s_addr)
6307 listener->options |= LI_O_CHK_MONNET;
6308
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006309 /* smart accept mode is automatic in HTTP mode */
6310 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6311 (curproxy->mode == PR_MODE_HTTP &&
6312 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6313 listener->options |= LI_O_NOQUICKACK;
6314
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006315 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006316 listener = listener->next;
6317 }
6318
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006319 /* Check multi-process mode compatibility for the current proxy */
6320 if (global.nbproc > 1) {
6321 int nbproc = 0;
6322 if (curproxy->bind_proc) {
6323 int proc;
6324 for (proc = 0; proc < global.nbproc; proc++) {
6325 if (curproxy->bind_proc & (1 << proc)) {
6326 nbproc++;
6327 }
6328 }
6329 } else {
6330 nbproc = global.nbproc;
6331 }
6332 if (curproxy->table.peers.name) {
6333 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6334 curproxy->id);
6335 cfgerr++;
6336 }
6337 if (nbproc > 1) {
6338 if (curproxy->uri_auth) {
6339 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6340 curproxy->id);
6341 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6342 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6343 curproxy->id);
6344 }
6345 }
6346 if (curproxy->appsession_name) {
6347 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6348 curproxy->id);
6349 }
6350 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6351 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6352 curproxy->id);
6353 }
6354 }
6355 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006356
6357 /* create the task associated with the proxy */
6358 curproxy->task = task_new();
6359 if (curproxy->task) {
6360 curproxy->task->context = curproxy;
6361 curproxy->task->process = manage_proxy;
6362 /* no need to queue, it will be done automatically if some
6363 * listener gets limited.
6364 */
6365 curproxy->task->expire = TICK_ETERNITY;
6366 } else {
6367 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6368 curproxy->id);
6369 cfgerr++;
6370 }
6371
Willy Tarreaubaaee002006-06-26 02:48:02 +02006372 curproxy = curproxy->next;
6373 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006374
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006375 /* Check multi-process mode compatibility */
6376 if (global.nbproc > 1) {
6377 if (global.stats_fe) {
6378 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6379 }
6380 }
6381
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006382 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6383 struct auth_users *curuser;
6384 int g;
6385
6386 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6387 unsigned int group_mask = 0;
6388 char *group = NULL;
6389
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006390 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006391 continue;
6392
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006393 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006394
6395 for (g = 0; g < curuserlist->grpcnt; g++)
6396 if (!strcmp(curuserlist->groups[g], group))
6397 break;
6398
6399 if (g == curuserlist->grpcnt) {
6400 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6401 curuserlist->name, group, curuser->user);
6402 err_code |= ERR_ALERT | ERR_FATAL;
6403 goto out;
6404 }
6405
6406 group_mask |= (1 << g);
6407 }
6408
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006409 free(curuser->u.groups);
6410 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006411 }
6412
6413 for (g = 0; g < curuserlist->grpcnt; g++) {
6414 char *user = NULL;
6415
6416 if (!curuserlist->groupusers[g])
6417 continue;
6418
6419 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6420 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6421 if (!strcmp(curuser->user, user))
6422 break;
6423
6424 if (!curuser) {
6425 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6426 curuserlist->name, user, curuserlist->groups[g]);
6427 err_code |= ERR_ALERT | ERR_FATAL;
6428 goto out;
6429 }
6430
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006431 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006432 }
6433
6434 free(curuserlist->groupusers[g]);
6435 }
6436
6437 free(curuserlist->groupusers);
6438
6439#ifdef DEBUG_AUTH
6440 for (g = 0; g < curuserlist->grpcnt; g++) {
6441 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6442
6443 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6444 if (curuser->group_mask & (1 << g))
6445 fprintf(stderr, " %s", curuser->user);
6446 }
6447
6448 fprintf(stderr, "\n");
6449 }
6450#endif
6451
Willy Tarreaufbb78422011-06-05 15:38:35 +02006452 }
6453
6454 /* automatically compute fullconn if not set. We must not do it in the
6455 * loop above because cross-references are not yet fully resolved.
6456 */
6457 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6458 /* If <fullconn> is not set, let's set it to 10% of the sum of
6459 * the possible incoming frontend's maxconns.
6460 */
6461 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6462 struct proxy *fe;
6463 int total = 0;
6464
6465 /* sum up the number of maxconns of frontends which
6466 * reference this backend at least once or which are
6467 * the same one ('listen').
6468 */
6469 for (fe = proxy; fe; fe = fe->next) {
6470 struct switching_rule *rule;
6471 struct hdr_exp *exp;
6472 int found = 0;
6473
6474 if (!(fe->cap & PR_CAP_FE))
6475 continue;
6476
6477 if (fe == curproxy) /* we're on a "listen" instance */
6478 found = 1;
6479
6480 if (fe->defbe.be == curproxy) /* "default_backend" */
6481 found = 1;
6482
6483 /* check if a "use_backend" rule matches */
6484 if (!found) {
6485 list_for_each_entry(rule, &fe->switching_rules, list) {
6486 if (rule->be.backend == curproxy) {
6487 found = 1;
6488 break;
6489 }
6490 }
6491 }
6492
6493 /* check if a "reqsetbe" rule matches */
6494 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6495 if (exp->action == ACT_SETBE &&
6496 (struct proxy *)exp->replace == curproxy) {
6497 found = 1;
6498 break;
6499 }
6500 }
6501
6502 /* now we've checked all possible ways to reference a backend
6503 * from a frontend.
6504 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006505 if (!found)
6506 continue;
6507 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006508 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006509 /* we have the sum of the maxconns in <total>. We only
6510 * keep 10% of that sum to set the default fullconn, with
6511 * a hard minimum of 1 (to avoid a divide by zero).
6512 */
6513 curproxy->fullconn = (total + 9) / 10;
6514 if (!curproxy->fullconn)
6515 curproxy->fullconn = 1;
6516 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006517 }
6518
Willy Tarreau056f5682010-06-06 15:51:11 +02006519 /* initialize stick-tables on backend capable proxies. This must not
6520 * be done earlier because the data size may be discovered while parsing
6521 * other proxies.
6522 */
6523 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006524 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006525
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006526 /*
6527 * Recount currently required checks.
6528 */
6529
6530 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6531 int optnum;
6532
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006533 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6534 if (curproxy->options & cfg_opts[optnum].val)
6535 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006536
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006537 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6538 if (curproxy->options2 & cfg_opts2[optnum].val)
6539 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006540 }
6541
Willy Tarreaubb925012009-07-23 13:36:36 +02006542 if (cfgerr > 0)
6543 err_code |= ERR_ALERT | ERR_FATAL;
6544 out:
6545 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006546}
6547
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006548/*
6549 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6550 * parsing sessions.
6551 */
6552void cfg_register_keywords(struct cfg_kw_list *kwl)
6553{
6554 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6555}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006557/*
6558 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6559 */
6560void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6561{
6562 LIST_DEL(&kwl->list);
6563 LIST_INIT(&kwl->list);
6564}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565
6566/*
6567 * Local variables:
6568 * c-indent-level: 8
6569 * c-basic-offset: 8
6570 * End:
6571 */