blob: 7456e472ec5919f777eb1471e07344c7ff591545 [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 Tarreau0f772532006-12-23 20:51:41 +010047#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020049#include <proto/lb_fwlc.h>
50#include <proto/lb_fwrr.h>
51#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010053#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020061#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010062#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010064#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065
66
Willy Tarreauf3c69202006-07-09 16:42:34 +020067/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
68 * ssl-hello-chk option to ensure that the remote server speaks SSL.
69 *
70 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
71 */
72const char sslv3_client_hello_pkt[] = {
73 "\x16" /* ContentType : 0x16 = Hanshake */
74 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
75 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
76 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
77 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
78 "\x03\x00" /* Hello Version : 0x0300 = v3 */
79 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
80 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
81 "\x00" /* Session ID length : empty (no session ID) */
82 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
83 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
84 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
85 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
86 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
87 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
88 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
89 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
90 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
91 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
92 "\x00\x38" "\x00\x39" "\x00\x3A"
93 "\x01" /* Compression Length : 0x01 = 1 byte for types */
94 "\x00" /* Compression Type : 0x00 = NULL compression */
95};
96
Willy Tarreau3842f002009-06-14 11:39:52 +020097/* various keyword modifiers */
98enum kw_mod {
99 KWM_STD = 0, /* normal */
100 KWM_NO, /* "no" prefixed before the keyword */
101 KWM_DEF, /* "default" prefixed before the keyword */
102};
103
Willy Tarreau13943ab2006-12-31 00:24:10 +0100104/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106 const char *name;
107 unsigned int val;
108 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100109 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100110 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100111};
112
113/* proxy->options */
114static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100115{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100116 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
117 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
118 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
119 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
120 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
121 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
122 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
126 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
128 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
129 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
130 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
131 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100132#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100133 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100134#else
135 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100136#endif
137
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139};
140
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100141/* proxy->options2 */
142static const struct cfg_opt cfg_opts2[] =
143{
144#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100148#else
149 { "splice-request", 0, 0, 0, 0 },
150 { "splice-response", 0, 0, 0, 0 },
151 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
154 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
155 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
156 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
157 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
158 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
161 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
162 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200163 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy 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] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100902 struct sockaddr_un *sk = str2sun(args[1]);
903 if (!sk) {
904 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
905 args[1], (int)sizeof(sk->sun_path) - 1);
906 err_code |= ERR_ALERT | ERR_FATAL;
907 goto out;
908 }
909 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100910 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +0100911 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100912 struct sockaddr_storage *sk = str2sa(args[1]);
913 if (!sk || sk->ss_family != AF_INET) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100914 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
David du Colombier6f5ccb12011-03-10 22:26:24 +0100918 logsrv.u.in = *(struct sockaddr_in *)sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100919 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +0100920 if (!logsrv.u.in.sin_port)
921 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
922 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923
924 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100925 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 global.logfac1 = facility;
927 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200928 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 }
930 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100931 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 global.logfac2 = facility;
933 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200934 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935 }
936 else {
937 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200938 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200940 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100941 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
942 char *name;
943 int len;
944
945 if (global.log_send_hostname != NULL) {
946 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
947 err_code |= ERR_ALERT;
948 goto out;
949 }
950
951 if (*(args[1]))
952 name = args[1];
953 else
954 name = hostname;
955
956 len = strlen(name);
957
958 /* We'll add a space after the name to respect the log format */
959 free(global.log_send_hostname);
960 global.log_send_hostname = malloc(len + 2);
961 snprintf(global.log_send_hostname, len + 2, "%s ", name);
962 }
Kevinm48936af2010-12-22 16:08:21 +0000963 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 free(global.log_tag);
970 global.log_tag = strdup(args[1]);
971 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200972 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
973 if (global.spread_checks != 0) {
974 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT;
976 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200977 }
978 if (*(args[1]) == 0) {
979 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200982 }
983 global.spread_checks = atol(args[1]);
984 if (global.spread_checks < 0 || global.spread_checks > 50) {
985 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200986 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200990 struct cfg_kw_list *kwl;
991 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200992 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200993
994 list_for_each_entry(kwl, &cfg_keywords.list, list) {
995 for (index = 0; kwl->kw[index].kw != NULL; index++) {
996 if (kwl->kw[index].section != CFG_GLOBAL)
997 continue;
998 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
999 /* prepare error message just in case */
1000 snprintf(trash, sizeof(trash),
1001 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001002 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1003 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001004 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001005 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001006 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001007 else if (rc > 0) {
1008 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 err_code |= ERR_WARN;
1010 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001011 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001012 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001013 }
1014 }
1015 }
1016
Willy Tarreaubaaee002006-06-26 02:48:02 +02001017 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001020
Willy Tarreau058e9072009-07-20 09:30:05 +02001021 out:
1022 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001023}
1024
Willy Tarreau97cb7802010-01-03 20:23:58 +01001025/* Perform the most basic initialization of a proxy :
1026 * memset(), list_init(*), reset_timeouts(*).
1027 */
1028static void init_new_proxy(struct proxy *p)
1029{
1030 memset(p, 0, sizeof(struct proxy));
1031 LIST_INIT(&p->pendconns);
1032 LIST_INIT(&p->acl);
Willy Tarreauff011f22011-01-06 17:51:27 +01001033 LIST_INIT(&p->http_req_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001034 LIST_INIT(&p->block_cond);
1035 LIST_INIT(&p->redirect_rules);
1036 LIST_INIT(&p->mon_fail_cond);
1037 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001038 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001039 LIST_INIT(&p->sticking_rules);
1040 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001041 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001042 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001043 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001044 LIST_INIT(&p->req_add);
1045 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001046
1047 /* Timeouts are defined as -1 */
1048 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001049 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001050}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001051
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001052void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001054 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001055 defproxy.mode = PR_MODE_TCP;
1056 defproxy.state = PR_STNEW;
1057 defproxy.maxconn = cfg_maxpconn;
1058 defproxy.conn_retries = CONN_RETRIES;
1059 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001060
1061 defproxy.defsrv.inter = DEF_CHKINTR;
1062 defproxy.defsrv.fastinter = 0;
1063 defproxy.defsrv.downinter = 0;
1064 defproxy.defsrv.rise = DEF_RISETIME;
1065 defproxy.defsrv.fall = DEF_FALLTIME;
1066 defproxy.defsrv.check_port = 0;
1067 defproxy.defsrv.maxqueue = 0;
1068 defproxy.defsrv.minconn = 0;
1069 defproxy.defsrv.maxconn = 0;
1070 defproxy.defsrv.slowstart = 0;
1071 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1072 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1073 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074}
1075
Willy Tarreauade5ec42010-01-28 19:33:49 +01001076
1077static int create_cond_regex_rule(const char *file, int line,
1078 struct proxy *px, int dir, int action, int flags,
1079 const char *cmd, const char *reg, const char *repl,
1080 const char **cond_start)
1081{
1082 regex_t *preg = NULL;
1083 const char *err;
1084 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001085 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001086
1087 if (px == &defproxy) {
1088 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto err;
1091 }
1092
1093 if (*reg == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto err;
1097 }
1098
1099 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1100 err_code |= ERR_WARN;
1101
Willy Tarreau5321c422010-01-28 20:35:13 +01001102 if (cond_start &&
1103 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1104 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1105 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1106 file, line, cmd);
1107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto err;
1109 }
1110 }
1111 else if (cond_start && **cond_start) {
1112 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1113 file, line, cmd, *cond_start);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto err;
1116 }
1117
1118 if (dir == ACL_DIR_REQ)
1119 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001120 else
1121 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001122
Willy Tarreauade5ec42010-01-28 19:33:49 +01001123 preg = calloc(1, sizeof(regex_t));
1124 if (!preg) {
1125 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1126 err_code = ERR_ALERT | ERR_FATAL;
1127 goto err;
1128 }
1129
1130 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1131 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1132 err_code = ERR_ALERT | ERR_FATAL;
1133 goto err;
1134 }
1135
1136 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001137 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001138 if (repl && err) {
1139 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1140 file, line, cmd, *err);
1141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto err;
1143 }
1144
1145 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1146 err_code |= ERR_WARN;
1147
1148 return err_code;
1149 err:
1150 free(preg);
1151 return err_code;
1152}
1153
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001155 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001156 * Returns the error code, 0 if OK, or any combination of :
1157 * - ERR_ABORT: must abort ASAP
1158 * - ERR_FATAL: we can continue parsing but not start the service
1159 * - ERR_WARN: a warning has been emitted
1160 * - ERR_ALERT: an alert has been emitted
1161 * Only the two first ones can stop processing, the two others are just
1162 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001164int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1165{
1166 static struct peers *curpeers = NULL;
1167 struct peer *newpeer = NULL;
1168 const char *err;
1169 int err_code = 0;
1170
1171 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1172
1173 err = invalid_char(args[1]);
1174 if (err) {
1175 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1176 file, linenum, *err, args[0], args[1]);
1177 err_code |= ERR_ALERT | ERR_FATAL;
1178 }
1179
1180 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1181 /*
1182 * If there are two proxies with the same name only following
1183 * combinations are allowed:
1184 */
1185 if (strcmp(curpeers->id, args[1]) == 0) {
1186 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1187 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1188 err_code |= ERR_WARN;
1189 }
1190 }
1191
1192 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1193 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1194 err_code |= ERR_ALERT | ERR_ABORT;
1195 goto out;
1196 }
1197
1198 curpeers->next = peers;
1199 peers = curpeers;
1200 curpeers->conf.file = file;
1201 curpeers->conf.line = linenum;
1202 curpeers->last_change = now.tv_sec;
1203 curpeers->id = strdup(args[1]);
1204 }
1205 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1206 char *rport, *raddr;
1207 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001208 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001209
1210 if (!*args[2]) {
1211 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1212 file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216
1217 err = invalid_char(args[1]);
1218 if (err) {
1219 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1220 file, linenum, *err, args[1]);
1221 err_code |= ERR_ALERT | ERR_FATAL;
1222 goto out;
1223 }
1224
1225 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1227 err_code |= ERR_ALERT | ERR_ABORT;
1228 goto out;
1229 }
1230
1231 /* the peers are linked backwards first */
1232 curpeers->count++;
1233 newpeer->next = curpeers->remote;
1234 curpeers->remote = newpeer;
1235 newpeer->peers = curpeers;
1236 newpeer->conf.file = file;
1237 newpeer->conf.line = linenum;
1238
1239 newpeer->last_change = now.tv_sec;
1240 newpeer->id = strdup(args[1]);
1241
1242 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001243 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001244 if (rport) {
1245 *rport++ = 0;
1246 realport = atol(rport);
1247 }
1248 if (!realport) {
1249 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1250 err_code |= ERR_ALERT | ERR_FATAL;
1251 goto out;
1252 }
1253
Willy Tarreaufab5a432011-03-04 15:31:53 +01001254 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001255 free(raddr);
1256 if (!sk) {
1257 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001262
1263 switch (newpeer->addr.ss_family) {
1264 case AF_INET:
1265 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1266 break;
1267 case AF_INET6:
1268 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1269 break;
1270 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001271
1272 if (strcmp(newpeer->id, localpeer) == 0) {
1273 /* Current is local peer, it define a frontend */
1274 newpeer->local = 1;
1275
1276 if (!curpeers->peers_fe) {
1277 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1278 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1279 err_code |= ERR_ALERT | ERR_ABORT;
1280 goto out;
1281 }
1282 curpeers->peers_fe->parent = curpeers;
1283
1284 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1285 LIST_INIT(&(curpeers->peers_fe)->acl);
1286 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1287 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1288 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1289 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1290 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1291 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1292
1293 proxy_reset_timeouts(curpeers->peers_fe);
1294
1295 curpeers->peers_fe->last_change = now.tv_sec;
1296 curpeers->peers_fe->id = strdup(args[1]);
1297 curpeers->peers_fe->cap = PR_CAP_FE;
1298 curpeers->peers_fe->maxconn = 65000;
1299 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1300 curpeers->peers_fe->timeout.connect = 5000;
1301 curpeers->peers_fe->accept = peer_accept;
1302 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001303 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001304 err_code |= ERR_FATAL;
1305 goto out;
1306 }
1307 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1308 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1309 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1310 curpeers->peers_fe->listen->accept = session_accept;
1311 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1312 curpeers->peers_fe->listen->handler = process_session;
1313 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1314 }
1315 }
1316 } /* neither "peer" nor "peers" */
1317 else if (*args[0] != 0) {
1318 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321 }
1322
1323out:
1324 return err_code;
1325}
1326
1327
Willy Tarreau3842f002009-06-14 11:39:52 +02001328int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329{
1330 static struct proxy *curproxy = NULL;
1331 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001332 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001333 int rc;
1334 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001335 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001336 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001337
Willy Tarreau977b8e42006-12-29 14:19:17 +01001338 if (!strcmp(args[0], "listen"))
1339 rc = PR_CAP_LISTEN;
1340 else if (!strcmp(args[0], "frontend"))
1341 rc = PR_CAP_FE | PR_CAP_RS;
1342 else if (!strcmp(args[0], "backend"))
1343 rc = PR_CAP_BE | PR_CAP_RS;
1344 else if (!strcmp(args[0], "ruleset"))
1345 rc = PR_CAP_RS;
1346 else
1347 rc = PR_CAP_NONE;
1348
1349 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 if (!*args[1]) {
1351 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1352 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001354 err_code |= ERR_ALERT | ERR_ABORT;
1355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001357
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001358 err = invalid_char(args[1]);
1359 if (err) {
1360 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1361 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001362 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001363 }
1364
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001365 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1366 /*
1367 * If there are two proxies with the same name only following
1368 * combinations are allowed:
1369 *
1370 * listen backend frontend ruleset
1371 * listen - - - -
1372 * backend - - OK -
1373 * frontend - OK - -
1374 * ruleset - - - -
1375 */
1376
1377 if (!strcmp(curproxy->id, args[1]) &&
1378 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1379 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001380 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1381 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1382 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001383 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001384 }
1385 }
1386
Willy Tarreaubaaee002006-06-26 02:48:02 +02001387 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1388 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001389 err_code |= ERR_ALERT | ERR_ABORT;
1390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001392
Willy Tarreau97cb7802010-01-03 20:23:58 +01001393 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 curproxy->next = proxy;
1395 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001396 curproxy->conf.file = file;
1397 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001398 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001400 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401
1402 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001403 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001404 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001405 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001406 err_code |= ERR_FATAL;
1407 goto out;
1408 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001409 new = curproxy->listen;
1410 while (new != last) {
1411 new->conf.file = file;
1412 new->conf.line = linenum;
1413 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001414 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 }
1417
1418 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001420 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001421
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001423 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001424 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001425 curproxy->no_options = defproxy.no_options;
1426 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001427 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001428 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001429 curproxy->except_net = defproxy.except_net;
1430 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001431 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001432 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001433
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001434 if (defproxy.fwdfor_hdr_len) {
1435 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1436 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1437 }
1438
Willy Tarreaub86db342009-11-30 11:50:16 +01001439 if (defproxy.orgto_hdr_len) {
1440 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1441 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1442 }
1443
Willy Tarreau977b8e42006-12-29 14:19:17 +01001444 if (curproxy->cap & PR_CAP_FE) {
1445 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001446 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001447 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001448
1449 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001450 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1451 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001452
1453 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455
Willy Tarreau977b8e42006-12-29 14:19:17 +01001456 if (curproxy->cap & PR_CAP_BE) {
1457 curproxy->fullconn = defproxy.fullconn;
1458 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001460 if (defproxy.check_req) {
1461 curproxy->check_req = calloc(1, defproxy.check_len);
1462 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1463 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001464 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466 if (defproxy.cookie_name)
1467 curproxy->cookie_name = strdup(defproxy.cookie_name);
1468 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001469 if (defproxy.cookie_domain)
1470 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001471
Willy Tarreau31936852010-10-06 16:59:56 +02001472 if (defproxy.cookie_maxidle)
1473 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1474
1475 if (defproxy.cookie_maxlife)
1476 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1477
Emeric Brun647caf12009-06-30 17:57:00 +02001478 if (defproxy.rdp_cookie_name)
1479 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1480 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1481
Willy Tarreau01732802007-11-01 22:48:15 +01001482 if (defproxy.url_param_name)
1483 curproxy->url_param_name = strdup(defproxy.url_param_name);
1484 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001485
Benoitaffb4812009-03-25 13:02:10 +01001486 if (defproxy.hh_name)
1487 curproxy->hh_name = strdup(defproxy.hh_name);
1488 curproxy->hh_len = defproxy.hh_len;
1489 curproxy->hh_match_domain = defproxy.hh_match_domain;
1490
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001491 if (defproxy.iface_name)
1492 curproxy->iface_name = strdup(defproxy.iface_name);
1493 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001495
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001496 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001497 if (defproxy.capture_name)
1498 curproxy->capture_name = strdup(defproxy.capture_name);
1499 curproxy->capture_namelen = defproxy.capture_namelen;
1500 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001504 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001505 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001506 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001507 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001508 curproxy->uri_auth = defproxy.uri_auth;
1509 curproxy->mon_net = defproxy.mon_net;
1510 curproxy->mon_mask = defproxy.mon_mask;
1511 if (defproxy.monitor_uri)
1512 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1513 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001514 if (defproxy.defbe.name)
1515 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001516 }
1517
1518 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001519 curproxy->timeout.connect = defproxy.timeout.connect;
1520 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001521 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001522 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001523 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001524 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001525 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001526 curproxy->source_addr = defproxy.source_addr;
1527 }
1528
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 curproxy->mode = defproxy.mode;
1530 curproxy->logfac1 = defproxy.logfac1;
1531 curproxy->logsrv1 = defproxy.logsrv1;
1532 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001533 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534 curproxy->logfac2 = defproxy.logfac2;
1535 curproxy->logsrv2 = defproxy.logsrv2;
1536 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001537 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001539 curproxy->conf.used_listener_id = EB_ROOT;
1540 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001541
Willy Tarreau93893792009-07-23 13:19:11 +02001542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 }
1544 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1545 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001546 /* FIXME-20070101: we should do this too at the end of the
1547 * config parsing to free all default values.
1548 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001549 free(defproxy.check_req);
1550 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001551 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001552 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001553 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001554 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001555 free(defproxy.capture_name);
1556 free(defproxy.monitor_uri);
1557 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001558 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001559 free(defproxy.fwdfor_hdr_name);
1560 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001561 free(defproxy.orgto_hdr_name);
1562 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001563
Willy Tarreaua534fea2008-08-03 12:19:50 +02001564 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001565 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001566
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 /* we cannot free uri_auth because it might already be used */
1568 init_default_instance();
1569 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001570 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 }
1573 else if (curproxy == NULL) {
1574 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001575 err_code |= ERR_ALERT | ERR_FATAL;
1576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 }
1578
Willy Tarreau977b8e42006-12-29 14:19:17 +01001579
1580 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001582 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001583 int cur_arg;
1584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 if (curproxy == &defproxy) {
1586 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001590 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001591 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592
Emeric Bruned760922010-10-22 17:59:25 +02001593 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001594 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001596 err_code |= ERR_ALERT | ERR_FATAL;
1597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001599
1600 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001601
1602 /* NOTE: the following line might create several listeners if there
1603 * are comma-separated IPs or port ranges. So all further processing
1604 * will have to be applied to all listeners created after last_listen.
1605 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001606 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001607 err_code |= ERR_ALERT | ERR_FATAL;
1608 goto out;
1609 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001610
Willy Tarreau90a570f2009-10-04 20:54:54 +02001611 new_listen = curproxy->listen;
1612 while (new_listen != last_listen) {
1613 new_listen->conf.file = file;
1614 new_listen->conf.line = linenum;
1615 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001616 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001617 }
1618
Emeric Bruned760922010-10-22 17:59:25 +02001619 /* Set default global rights and owner for unix bind */
1620 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1621 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1622 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001623 cur_arg = 2;
1624 while (*(args[cur_arg])) {
1625 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1626#ifdef SO_BINDTODEVICE
1627 struct listener *l;
1628
Emeric Bruned760922010-10-22 17:59:25 +02001629 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1630 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1631 file, linenum, args[0], args[cur_arg]);
1632 err_code |= ERR_ALERT | ERR_FATAL;
1633 goto out;
1634 }
1635
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001636 if (!*args[cur_arg + 1]) {
1637 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1638 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001639 err_code |= ERR_ALERT | ERR_FATAL;
1640 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001641 }
1642
1643 for (l = curproxy->listen; l != last_listen; l = l->next)
1644 l->interface = strdup(args[cur_arg + 1]);
1645
1646 global.last_checks |= LSTCHK_NETADM;
1647
1648 cur_arg += 2;
1649 continue;
1650#else
1651 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1652 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001655#endif
1656 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001657 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1658#ifdef TCP_MAXSEG
1659 struct listener *l;
1660 int mss;
1661
Emeric Bruned760922010-10-22 17:59:25 +02001662 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1663 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1664 file, linenum, args[0], args[cur_arg]);
1665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
1667 }
1668
Willy Tarreaube1b9182009-06-14 18:48:19 +02001669 if (!*args[cur_arg + 1]) {
1670 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1671 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_FATAL;
1673 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001674 }
1675
Willy Tarreau48a7e722010-12-24 15:26:39 +01001676 mss = atoi(args[cur_arg + 1]);
1677 if (!mss || abs(mss) > 65535) {
1678 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001679 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001680 err_code |= ERR_ALERT | ERR_FATAL;
1681 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001682 }
1683
1684 for (l = curproxy->listen; l != last_listen; l = l->next)
1685 l->maxseg = mss;
1686
1687 cur_arg += 2;
1688 continue;
1689#else
1690 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1691 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001692 err_code |= ERR_ALERT | ERR_FATAL;
1693 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001694#endif
1695 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001696
1697 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1698#ifdef TCP_DEFER_ACCEPT
1699 struct listener *l;
1700
1701 for (l = curproxy->listen; l != last_listen; l = l->next)
1702 l->options |= LI_O_DEF_ACCEPT;
1703
1704 cur_arg ++;
1705 continue;
1706#else
1707 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1708 file, linenum, args[0], args[cur_arg]);
1709 err_code |= ERR_ALERT | ERR_FATAL;
1710 goto out;
1711#endif
1712 }
1713
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001714 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001715#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001716 struct listener *l;
1717
Emeric Bruned760922010-10-22 17:59:25 +02001718 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1719 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1720 file, linenum, args[0], args[cur_arg]);
1721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
1724
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001725 for (l = curproxy->listen; l != last_listen; l = l->next)
1726 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001727
1728 cur_arg ++;
1729 continue;
1730#else
1731 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1732 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001733 err_code |= ERR_ALERT | ERR_FATAL;
1734 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001735#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001736 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001737
Willy Tarreau8a956912010-10-15 14:27:08 +02001738 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1739 struct listener *l;
1740
1741 for (l = curproxy->listen; l != last_listen; l = l->next)
1742 l->options |= LI_O_ACC_PROXY;
1743
1744 cur_arg ++;
1745 continue;
1746 }
1747
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001748 if (!strcmp(args[cur_arg], "name")) {
1749 struct listener *l;
1750
1751 for (l = curproxy->listen; l != last_listen; l = l->next)
1752 l->name = strdup(args[cur_arg + 1]);
1753
1754 cur_arg += 2;
1755 continue;
1756 }
1757
1758 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001759 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001760 struct listener *l;
1761
1762 if (curproxy->listen->next != last_listen) {
1763 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1764 file, linenum, args[cur_arg]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767 }
1768
1769 if (!*args[cur_arg + 1]) {
1770 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1771 file, linenum, args[cur_arg]);
1772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
1774 }
1775
1776 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001777 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001778
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001779 if (curproxy->listen->luid <= 0) {
1780 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001781 file, linenum);
1782 err_code |= ERR_ALERT | ERR_FATAL;
1783 goto out;
1784 }
1785
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001786 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1787 if (node) {
1788 l = container_of(node, struct listener, conf.id);
1789 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1790 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
1793 }
1794 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1795
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001796 cur_arg += 2;
1797 continue;
1798 }
1799
Emeric Bruned760922010-10-22 17:59:25 +02001800 if (!strcmp(args[cur_arg], "mode")) {
1801
1802 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1803 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1804 file, linenum, args[0], args[cur_arg]);
1805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
1809 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1810
1811 cur_arg += 2;
1812 continue;
1813 }
1814
1815 if (!strcmp(args[cur_arg], "uid")) {
1816
1817 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1818 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1819 file, linenum, args[0], args[cur_arg]);
1820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
1822 }
1823
1824 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1825 cur_arg += 2;
1826 continue;
1827 }
1828
1829 if (!strcmp(args[cur_arg], "gid")) {
1830
1831 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1832 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1833 file, linenum, args[0], args[cur_arg]);
1834 err_code |= ERR_ALERT | ERR_FATAL;
1835 goto out;
1836 }
1837
1838 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1839 cur_arg += 2;
1840 continue;
1841 }
1842
1843 if (!strcmp(args[cur_arg], "user")) {
1844 struct passwd *user;
1845
1846 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1847 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1848 file, linenum, args[0], args[cur_arg]);
1849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
1851 }
1852 user = getpwnam(args[cur_arg + 1]);
1853 if (!user) {
1854 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1855 file, linenum, args[0], args[cur_arg + 1 ]);
1856 err_code |= ERR_ALERT | ERR_FATAL;
1857 goto out;
1858 }
1859
1860 curproxy->listen->perm.ux.uid = user->pw_uid;
1861 cur_arg += 2;
1862 continue;
1863 }
1864
1865 if (!strcmp(args[cur_arg], "group")) {
1866 struct group *group;
1867
1868 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1869 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1870 file, linenum, args[0], args[cur_arg]);
1871 err_code |= ERR_ALERT | ERR_FATAL;
1872 goto out;
1873 }
1874 group = getgrnam(args[cur_arg + 1]);
1875 if (!group) {
1876 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1877 file, linenum, args[0], args[cur_arg + 1 ]);
1878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
1880 }
1881
1882 curproxy->listen->perm.ux.gid = group->gr_gid;
1883 cur_arg += 2;
1884 continue;
1885 }
1886
Willy Tarreau8a956912010-10-15 14:27:08 +02001887 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 +01001888 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001891 }
Willy Tarreau93893792009-07-23 13:19:11 +02001892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001893 }
1894 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1895 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1896 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1897 file, linenum, args[0]);
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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001901 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001902 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 /* flush useless bits */
1905 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001908 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001909 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001910 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911
Willy Tarreau1c47f852006-07-09 08:22:27 +02001912 if (!*args[1]) {
1913 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1914 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001915 err_code |= ERR_ALERT | ERR_FATAL;
1916 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001917 }
1918
Willy Tarreaua534fea2008-08-03 12:19:50 +02001919 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001920 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001921 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001922 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001923 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1924
Willy Tarreau93893792009-07-23 13:19:11 +02001925 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001926 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001927 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1928 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1929 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1930 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1931 else {
1932 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_ALERT | ERR_FATAL;
1934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 }
1936 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001937 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001938 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001939
1940 if (curproxy == &defproxy) {
1941 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_ALERT | ERR_FATAL;
1944 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001945 }
1946
1947 if (!*args[1]) {
1948 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_FATAL;
1951 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001952 }
1953
1954 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001955 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001956
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001957 if (curproxy->uuid <= 0) {
1958 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001959 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_FATAL;
1961 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001962 }
1963
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001964 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1965 if (node) {
1966 struct proxy *target = container_of(node, struct proxy, conf.id);
1967 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1968 file, linenum, proxy_type_str(curproxy), curproxy->id,
1969 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1970 err_code |= ERR_ALERT | ERR_FATAL;
1971 goto out;
1972 }
1973 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001974 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001975 else if (!strcmp(args[0], "description")) {
1976 int i, len=0;
1977 char *d;
1978
Cyril Bonté99ed3272010-01-24 23:29:44 +01001979 if (curproxy == &defproxy) {
1980 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1981 file, linenum, args[0]);
1982 err_code |= ERR_ALERT | ERR_FATAL;
1983 goto out;
1984 }
1985
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001986 if (!*args[1]) {
1987 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1988 file, linenum, args[0]);
1989 return -1;
1990 }
1991
1992 for(i=1; *args[i]; i++)
1993 len += strlen(args[i])+1;
1994
1995 d = (char *)calloc(1, len);
1996 curproxy->desc = d;
1997
1998 d += sprintf(d, "%s", args[1]);
1999 for(i=2; *args[i]; i++)
2000 d += sprintf(d, " %s", args[i]);
2001
2002 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2004 curproxy->state = PR_STSTOPPED;
2005 }
2006 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2007 curproxy->state = PR_STNEW;
2008 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002009 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2010 int cur_arg = 1;
2011 unsigned int set = 0;
2012
2013 while (*args[cur_arg]) {
2014 int u;
2015 if (strcmp(args[cur_arg], "all") == 0) {
2016 set = 0;
2017 break;
2018 }
2019 else if (strcmp(args[cur_arg], "odd") == 0) {
2020 set |= 0x55555555;
2021 }
2022 else if (strcmp(args[cur_arg], "even") == 0) {
2023 set |= 0xAAAAAAAA;
2024 }
2025 else {
2026 u = str2uic(args[cur_arg]);
2027 if (u < 1 || u > 32) {
2028 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2029 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002030 err_code |= ERR_ALERT | ERR_FATAL;
2031 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002032 }
2033 if (u > global.nbproc) {
2034 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2035 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002037 }
2038 set |= 1 << (u - 1);
2039 }
2040 cur_arg++;
2041 }
2042 curproxy->bind_proc = set;
2043 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002044 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002045 if (curproxy == &defproxy) {
2046 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_ALERT | ERR_FATAL;
2048 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002049 }
2050
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002051 err = invalid_char(args[1]);
2052 if (err) {
2053 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2054 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002055 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002056 }
2057
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002058 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2059 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2060 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002063 }
2064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002065 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2066 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002069 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002070
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 if (*(args[1]) == 0) {
2072 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2073 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002077
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002078 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002079 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002080 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002081 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002082 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 curproxy->cookie_name = strdup(args[1]);
2084 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002085
Willy Tarreaubaaee002006-06-26 02:48:02 +02002086 cur_arg = 2;
2087 while (*(args[cur_arg])) {
2088 if (!strcmp(args[cur_arg], "rewrite")) {
2089 curproxy->options |= PR_O_COOK_RW;
2090 }
2091 else if (!strcmp(args[cur_arg], "indirect")) {
2092 curproxy->options |= PR_O_COOK_IND;
2093 }
2094 else if (!strcmp(args[cur_arg], "insert")) {
2095 curproxy->options |= PR_O_COOK_INS;
2096 }
2097 else if (!strcmp(args[cur_arg], "nocache")) {
2098 curproxy->options |= PR_O_COOK_NOC;
2099 }
2100 else if (!strcmp(args[cur_arg], "postonly")) {
2101 curproxy->options |= PR_O_COOK_POST;
2102 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002103 else if (!strcmp(args[cur_arg], "preserve")) {
2104 curproxy->options2 |= PR_O2_COOK_PSV;
2105 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 else if (!strcmp(args[cur_arg], "prefix")) {
2107 curproxy->options |= PR_O_COOK_PFX;
2108 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002109 else if (!strcmp(args[cur_arg], "domain")) {
2110 if (!*args[cur_arg + 1]) {
2111 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2112 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
2114 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002115 }
2116
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002117 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002118 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002119 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2120 " dots nor does not start with a dot."
2121 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002122 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002123 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002124 }
2125
2126 err = invalid_domainchar(args[cur_arg + 1]);
2127 if (err) {
2128 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2129 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002132 }
2133
Willy Tarreau68a897b2009-12-03 23:28:34 +01002134 if (!curproxy->cookie_domain) {
2135 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2136 } else {
2137 /* one domain was already specified, add another one by
2138 * building the string which will be returned along with
2139 * the cookie.
2140 */
2141 char *new_ptr;
2142 int new_len = strlen(curproxy->cookie_domain) +
2143 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2144 new_ptr = malloc(new_len);
2145 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2146 free(curproxy->cookie_domain);
2147 curproxy->cookie_domain = new_ptr;
2148 }
Willy Tarreau31936852010-10-06 16:59:56 +02002149 cur_arg++;
2150 }
2151 else if (!strcmp(args[cur_arg], "maxidle")) {
2152 unsigned int maxidle;
2153 const char *res;
2154
2155 if (!*args[cur_arg + 1]) {
2156 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2157 file, linenum, args[cur_arg]);
2158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
2160 }
2161
2162 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2163 if (res) {
2164 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2165 file, linenum, *res, args[cur_arg]);
2166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
2168 }
2169 curproxy->cookie_maxidle = maxidle;
2170 cur_arg++;
2171 }
2172 else if (!strcmp(args[cur_arg], "maxlife")) {
2173 unsigned int maxlife;
2174 const char *res;
2175
2176 if (!*args[cur_arg + 1]) {
2177 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2178 file, linenum, args[cur_arg]);
2179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
2181 }
2182
2183 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2184 if (res) {
2185 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2186 file, linenum, *res, args[cur_arg]);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002191 cur_arg++;
2192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002194 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 +02002195 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002196 err_code |= ERR_ALERT | ERR_FATAL;
2197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 }
2199 cur_arg++;
2200 }
2201 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2202 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2203 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002205 }
2206
2207 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2208 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2209 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002210 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002211 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002212
2213 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2214 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2215 file, linenum);
2216 err_code |= ERR_ALERT | ERR_FATAL;
2217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002219 else if (!strcmp(args[0], "persist")) { /* persist */
2220 if (*(args[1]) == 0) {
2221 Alert("parsing [%s:%d] : missing persist method.\n",
2222 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002225 }
2226
2227 if (!strncmp(args[1], "rdp-cookie", 10)) {
2228 curproxy->options2 |= PR_O2_RDPC_PRST;
2229
Emeric Brunb982a3d2010-01-04 15:45:53 +01002230 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002231 const char *beg, *end;
2232
2233 beg = args[1] + 11;
2234 end = strchr(beg, ')');
2235
2236 if (!end || end == beg) {
2237 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2238 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002241 }
2242
2243 free(curproxy->rdp_cookie_name);
2244 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2245 curproxy->rdp_cookie_len = end-beg;
2246 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002247 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002248 free(curproxy->rdp_cookie_name);
2249 curproxy->rdp_cookie_name = strdup("msts");
2250 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2251 }
2252 else { /* syntax */
2253 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2254 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_ALERT | ERR_FATAL;
2256 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002257 }
2258 }
2259 else {
2260 Alert("parsing [%s:%d] : unknown persist method.\n",
2261 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002264 }
2265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002267 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002269 if (curproxy == &defproxy) {
2270 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
2273 }
2274
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002276 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002279 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 }
2284 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002285 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002286 curproxy->appsession_name = strdup(args[1]);
2287 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2288 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002289 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2290 if (err) {
2291 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2292 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002295 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002296 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002297
Willy Tarreau51041c72007-09-09 21:56:53 +02002298 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2299 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_ABORT;
2301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002303
2304 cur_arg = 6;
2305 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002306 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2307 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002308 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002309 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002310 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002311 } else if (!strcmp(args[cur_arg], "prefix")) {
2312 curproxy->options2 |= PR_O2_AS_PFX;
2313 } else if (!strcmp(args[cur_arg], "mode")) {
2314 if (!*args[cur_arg + 1]) {
2315 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2316 file, linenum, args[0], args[cur_arg]);
2317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
2319 }
2320
2321 cur_arg++;
2322 if (!strcmp(args[cur_arg], "query-string")) {
2323 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2324 curproxy->options2 |= PR_O2_AS_M_QS;
2325 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2326 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2327 curproxy->options2 |= PR_O2_AS_M_PP;
2328 } else {
2329 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2330 err_code |= ERR_ALERT | ERR_FATAL;
2331 goto out;
2332 }
2333 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002334 cur_arg++;
2335 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 } /* Url App Session */
2337 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002338 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002340
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002342 if (curproxy == &defproxy) {
2343 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
2346 }
2347
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 if (*(args[4]) == 0) {
2349 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2350 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002351 err_code |= ERR_ALERT | ERR_FATAL;
2352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002354 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 curproxy->capture_name = strdup(args[2]);
2356 curproxy->capture_namelen = strlen(curproxy->capture_name);
2357 curproxy->capture_len = atol(args[4]);
2358 if (curproxy->capture_len >= CAPTURE_LEN) {
2359 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2360 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002361 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 curproxy->capture_len = CAPTURE_LEN - 1;
2363 }
2364 curproxy->to_log |= LW_COOKIE;
2365 }
2366 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2367 struct cap_hdr *hdr;
2368
2369 if (curproxy == &defproxy) {
2370 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 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
2374
2375 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2376 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2377 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002378 err_code |= ERR_ALERT | ERR_FATAL;
2379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381
2382 hdr = calloc(sizeof(struct cap_hdr), 1);
2383 hdr->next = curproxy->req_cap;
2384 hdr->name = strdup(args[3]);
2385 hdr->namelen = strlen(args[3]);
2386 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002387 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 hdr->index = curproxy->nb_req_cap++;
2389 curproxy->req_cap = hdr;
2390 curproxy->to_log |= LW_REQHDR;
2391 }
2392 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2393 struct cap_hdr *hdr;
2394
2395 if (curproxy == &defproxy) {
2396 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 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
2400
2401 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2402 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2403 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
2405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 }
2407 hdr = calloc(sizeof(struct cap_hdr), 1);
2408 hdr->next = curproxy->rsp_cap;
2409 hdr->name = strdup(args[3]);
2410 hdr->namelen = strlen(args[3]);
2411 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002412 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413 hdr->index = curproxy->nb_rsp_cap++;
2414 curproxy->rsp_cap = hdr;
2415 curproxy->to_log |= LW_RSPHDR;
2416 }
2417 else {
2418 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 }
2423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002427
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 if (*(args[1]) == 0) {
2429 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2430 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 }
2434 curproxy->conn_retries = atol(args[1]);
2435 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002436 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002437 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002438
2439 if (curproxy == &defproxy) {
2440 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
2443 }
2444
Willy Tarreauff011f22011-01-06 17:51:27 +01002445 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 +01002446 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2447 file, linenum, args[0]);
2448 err_code |= ERR_WARN;
2449 }
2450
Willy Tarreauff011f22011-01-06 17:51:27 +01002451 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002452
Willy Tarreauff011f22011-01-06 17:51:27 +01002453 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002454 err_code |= ERR_ALERT | ERR_ABORT;
2455 goto out;
2456 }
2457
Willy Tarreauff011f22011-01-06 17:51:27 +01002458 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2459 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002460 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002461 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002462 if (curproxy == &defproxy) {
2463 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002466 }
2467
Willy Tarreauef6494c2010-01-28 17:12:36 +01002468 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002469 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2470 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002471 err_code |= ERR_ALERT | ERR_FATAL;
2472 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002473 }
2474
Willy Tarreauef6494c2010-01-28 17:12:36 +01002475 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002476 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2477 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002478 err_code |= ERR_ALERT | ERR_FATAL;
2479 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002480 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002481
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002482 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002483 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002484 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002485 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002486 struct redirect_rule *rule;
2487 int cur_arg;
2488 int type = REDIRECT_TYPE_NONE;
2489 int code = 302;
2490 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002491 char *cookie = NULL;
2492 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002493 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002494
Cyril Bonté99ed3272010-01-24 23:29:44 +01002495 if (curproxy == &defproxy) {
2496 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002501 cur_arg = 1;
2502 while (*(args[cur_arg])) {
2503 if (!strcmp(args[cur_arg], "location")) {
2504 if (!*args[cur_arg + 1]) {
2505 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2506 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002509 }
2510
2511 type = REDIRECT_TYPE_LOCATION;
2512 cur_arg++;
2513 destination = args[cur_arg];
2514 }
2515 else if (!strcmp(args[cur_arg], "prefix")) {
2516 if (!*args[cur_arg + 1]) {
2517 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2518 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002521 }
2522
2523 type = REDIRECT_TYPE_PREFIX;
2524 cur_arg++;
2525 destination = args[cur_arg];
2526 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002527 else if (!strcmp(args[cur_arg], "set-cookie")) {
2528 if (!*args[cur_arg + 1]) {
2529 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2530 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002533 }
2534
2535 cur_arg++;
2536 cookie = args[cur_arg];
2537 cookie_set = 1;
2538 }
2539 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2540 if (!*args[cur_arg + 1]) {
2541 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2542 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002545 }
2546
2547 cur_arg++;
2548 cookie = args[cur_arg];
2549 cookie_set = 0;
2550 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002551 else if (!strcmp(args[cur_arg],"code")) {
2552 if (!*args[cur_arg + 1]) {
2553 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2554 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002557 }
2558 cur_arg++;
2559 code = atol(args[cur_arg]);
2560 if (code < 301 || code > 303) {
2561 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2562 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002565 }
2566 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002567 else if (!strcmp(args[cur_arg],"drop-query")) {
2568 flags |= REDIRECT_FLAG_DROP_QS;
2569 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002570 else if (!strcmp(args[cur_arg],"append-slash")) {
2571 flags |= REDIRECT_FLAG_APPEND_SLASH;
2572 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002573 else if (strcmp(args[cur_arg], "if") == 0 ||
2574 strcmp(args[cur_arg], "unless") == 0) {
2575 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2576 if (!cond) {
2577 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2578 file, linenum, args[0]);
2579 err_code |= ERR_ALERT | ERR_FATAL;
2580 goto out;
2581 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002582 break;
2583 }
2584 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002585 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 +02002586 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002589 }
2590 cur_arg++;
2591 }
2592
2593 if (type == REDIRECT_TYPE_NONE) {
2594 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002598 }
2599
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2601 rule->cond = cond;
2602 rule->rdr_str = strdup(destination);
2603 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002604 if (cookie) {
2605 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002606 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002607 */
2608 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002609 if (cookie_set) {
2610 rule->cookie_str = malloc(rule->cookie_len + 10);
2611 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2612 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2613 rule->cookie_len += 9;
2614 } else {
2615 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002616 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002617 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2618 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002619 }
2620 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002621 rule->type = type;
2622 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002623 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002624 LIST_INIT(&rule->list);
2625 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002626 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2627 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002628 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002629 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002630 struct switching_rule *rule;
2631
Willy Tarreaub099aca2008-10-12 17:26:37 +02002632 if (curproxy == &defproxy) {
2633 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002636 }
2637
Willy Tarreau55ea7572007-06-17 19:56:27 +02002638 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002639 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002640
2641 if (*(args[1]) == 0) {
2642 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002645 }
2646
Willy Tarreauef6494c2010-01-28 17:12:36 +01002647 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002648 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2649 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002652 }
2653
Willy Tarreauef6494c2010-01-28 17:12:36 +01002654 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002655 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002656 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002657 err_code |= ERR_ALERT | ERR_FATAL;
2658 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002659 }
2660
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002661 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002662
Willy Tarreau55ea7572007-06-17 19:56:27 +02002663 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2664 rule->cond = cond;
2665 rule->be.name = strdup(args[1]);
2666 LIST_INIT(&rule->list);
2667 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2668 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002669 else if ((!strcmp(args[0], "force-persist")) ||
2670 (!strcmp(args[0], "ignore-persist"))) {
2671 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002672
2673 if (curproxy == &defproxy) {
2674 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
2677 }
2678
2679 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2680 err_code |= ERR_WARN;
2681
Willy Tarreauef6494c2010-01-28 17:12:36 +01002682 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002683 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2684 file, linenum, args[0]);
2685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
2687 }
2688
Willy Tarreauef6494c2010-01-28 17:12:36 +01002689 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002690 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2691 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
2695
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002696 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002697
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002698 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002699 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002700 if (!strcmp(args[0], "force-persist")) {
2701 rule->type = PERSIST_TYPE_FORCE;
2702 } else {
2703 rule->type = PERSIST_TYPE_IGNORE;
2704 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002705 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002706 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002707 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002708 else if (!strcmp(args[0], "stick-table")) {
2709 int myidx = 1;
2710
Emeric Brun32da3c42010-09-23 18:39:19 +02002711 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002712 curproxy->table.type = (unsigned int)-1;
2713 while (*args[myidx]) {
2714 const char *err;
2715
2716 if (strcmp(args[myidx], "size") == 0) {
2717 myidx++;
2718 if (!*(args[myidx])) {
2719 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2720 file, linenum, args[myidx-1]);
2721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
2723 }
2724 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2725 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2726 file, linenum, *err, args[myidx-1]);
2727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
2729 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002730 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002731 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002732 else if (strcmp(args[myidx], "peers") == 0) {
2733 myidx++;
2734 if (!*(args[myidx])) {
2735 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2736 file, linenum, args[myidx-1]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740 curproxy->table.peers.name = strdup(args[myidx++]);
2741 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002742 else if (strcmp(args[myidx], "expire") == 0) {
2743 myidx++;
2744 if (!*(args[myidx])) {
2745 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2746 file, linenum, args[myidx-1]);
2747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
2749 }
2750 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2751 if (err) {
2752 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2753 file, linenum, *err, args[myidx-1]);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002758 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002759 }
2760 else if (strcmp(args[myidx], "nopurge") == 0) {
2761 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002762 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002763 }
2764 else if (strcmp(args[myidx], "type") == 0) {
2765 myidx++;
2766 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2767 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2768 file, linenum, args[myidx]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002772 /* myidx already points to next arg */
2773 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002774 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002775 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002776 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002777
2778 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002779 nw = args[myidx];
2780 while (*nw) {
2781 /* the "store" keyword supports a comma-separated list */
2782 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002783 sa = NULL; /* store arg */
2784 while (*nw && *nw != ',') {
2785 if (*nw == '(') {
2786 *nw = 0;
2787 sa = ++nw;
2788 while (*nw != ')') {
2789 if (!*nw) {
2790 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2791 file, linenum, args[0], cw);
2792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
2794 }
2795 nw++;
2796 }
2797 *nw = '\0';
2798 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002799 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002800 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002801 if (*nw)
2802 *nw++ = '\0';
2803 type = stktable_get_data_type(cw);
2804 if (type < 0) {
2805 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2806 file, linenum, args[0], cw);
2807 err_code |= ERR_ALERT | ERR_FATAL;
2808 goto out;
2809 }
Willy Tarreauac782882010-06-20 10:41:54 +02002810
2811 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2812 switch (err) {
2813 case PE_NONE: break;
2814 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002815 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2816 file, linenum, args[0], cw);
2817 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002818 break;
2819
2820 case PE_ARG_MISSING:
2821 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2822 file, linenum, args[0], cw);
2823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
2825
2826 case PE_ARG_NOT_USED:
2827 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2828 file, linenum, args[0], cw);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831
2832 default:
2833 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2834 file, linenum, args[0], cw);
2835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002837 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002838 }
2839 myidx++;
2840 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002841 else {
2842 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2843 file, linenum, args[myidx]);
2844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002846 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002847 }
2848
2849 if (!curproxy->table.size) {
2850 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2851 file, linenum);
2852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854 }
2855
2856 if (curproxy->table.type == (unsigned int)-1) {
2857 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2858 file, linenum);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862 }
2863 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002864 struct sticking_rule *rule;
2865 struct pattern_expr *expr;
2866 int myidx = 0;
2867 const char *name = NULL;
2868 int flags;
2869
2870 if (curproxy == &defproxy) {
2871 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
2874 }
2875
2876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2877 err_code |= ERR_WARN;
2878 goto out;
2879 }
2880
2881 myidx++;
2882 if ((strcmp(args[myidx], "store") == 0) ||
2883 (strcmp(args[myidx], "store-request") == 0)) {
2884 myidx++;
2885 flags = STK_IS_STORE;
2886 }
2887 else if (strcmp(args[myidx], "store-response") == 0) {
2888 myidx++;
2889 flags = STK_IS_STORE | STK_ON_RSP;
2890 }
2891 else if (strcmp(args[myidx], "match") == 0) {
2892 myidx++;
2893 flags = STK_IS_MATCH;
2894 }
2895 else if (strcmp(args[myidx], "on") == 0) {
2896 myidx++;
2897 flags = STK_IS_MATCH | STK_IS_STORE;
2898 }
2899 else {
2900 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
2903 }
2904
2905 if (*(args[myidx]) == 0) {
2906 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2907 err_code |= ERR_ALERT | ERR_FATAL;
2908 goto out;
2909 }
2910
Emeric Brun485479d2010-09-23 18:02:19 +02002911 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002912 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002913 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
2916 }
2917
2918 if (flags & STK_ON_RSP) {
2919 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2920 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2921 file, linenum, args[0], expr->fetch->kw);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925 } else {
2926 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2927 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2928 file, linenum, args[0], expr->fetch->kw);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
2932 }
2933
2934 if (strcmp(args[myidx], "table") == 0) {
2935 myidx++;
2936 name = args[myidx++];
2937 }
2938
Willy Tarreauef6494c2010-01-28 17:12:36 +01002939 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2940 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2942 file, linenum, args[0]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002946 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002947 else if (*(args[myidx])) {
2948 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2949 file, linenum, args[0], args[myidx]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
Emeric Brun97679e72010-09-23 17:56:44 +02002953 if (flags & STK_ON_RSP)
2954 err_code |= warnif_cond_requires_req(cond, file, linenum);
2955 else
2956 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002957
Emeric Brunb982a3d2010-01-04 15:45:53 +01002958 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2959 rule->cond = cond;
2960 rule->expr = expr;
2961 rule->flags = flags;
2962 rule->table.name = name ? strdup(name) : NULL;
2963 LIST_INIT(&rule->list);
2964 if (flags & STK_ON_RSP)
2965 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2966 else
2967 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002969 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002971 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002972
Willy Tarreaubaaee002006-06-26 02:48:02 +02002973 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2974 curproxy->uri_auth = NULL; /* we must detach from the default config */
2975
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002976 if (!*args[1]) {
2977 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002978 } else if (!strcmp(args[1], "admin")) {
2979 struct stats_admin_rule *rule;
2980
2981 if (curproxy == &defproxy) {
2982 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986
2987 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2988 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2989 err_code |= ERR_ALERT | ERR_ABORT;
2990 goto out;
2991 }
2992
2993 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2994 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2995 file, linenum, args[0], args[1]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3000 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3001 file, linenum, args[0], args[1]);
3002 err_code |= ERR_ALERT | ERR_FATAL;
3003 goto out;
3004 }
3005
3006 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3007
3008 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3009 rule->cond = cond;
3010 LIST_INIT(&rule->list);
3011 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 } else if (!strcmp(args[1], "uri")) {
3013 if (*(args[2]) == 0) {
3014 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003015 err_code |= ERR_ALERT | ERR_FATAL;
3016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3018 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_ABORT;
3020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 }
3022 } else if (!strcmp(args[1], "realm")) {
3023 if (*(args[2]) == 0) {
3024 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3028 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003029 err_code |= ERR_ALERT | ERR_ABORT;
3030 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003032 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003033 unsigned interval;
3034
3035 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3036 if (err) {
3037 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3038 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003041 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3042 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003043 err_code |= ERR_ALERT | ERR_ABORT;
3044 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003045 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003046 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003047 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003048
3049 if (curproxy == &defproxy) {
3050 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
3053 }
3054
3055 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3056 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3057 err_code |= ERR_ALERT | ERR_ABORT;
3058 goto out;
3059 }
3060
Willy Tarreauff011f22011-01-06 17:51:27 +01003061 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3062 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003063 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3064 file, linenum, args[0]);
3065 err_code |= ERR_WARN;
3066 }
3067
Willy Tarreauff011f22011-01-06 17:51:27 +01003068 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003069
Willy Tarreauff011f22011-01-06 17:51:27 +01003070 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003071 err_code |= ERR_ALERT | ERR_ABORT;
3072 goto out;
3073 }
3074
Willy Tarreauff011f22011-01-06 17:51:27 +01003075 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3076 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003077
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 } else if (!strcmp(args[1], "auth")) {
3079 if (*(args[2]) == 0) {
3080 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3084 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003085 err_code |= ERR_ALERT | ERR_ABORT;
3086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 }
3088 } else if (!strcmp(args[1], "scope")) {
3089 if (*(args[2]) == 0) {
3090 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3094 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_ALERT | ERR_ABORT;
3096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 }
3098 } else if (!strcmp(args[1], "enable")) {
3099 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3100 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_ABORT;
3102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003104 } else if (!strcmp(args[1], "hide-version")) {
3105 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3106 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003107 err_code |= ERR_ALERT | ERR_ABORT;
3108 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003109 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003110 } else if (!strcmp(args[1], "show-legends")) {
3111 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3112 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3113 err_code |= ERR_ALERT | ERR_ABORT;
3114 goto out;
3115 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003116 } else if (!strcmp(args[1], "show-node")) {
3117
3118 if (*args[2]) {
3119 int i;
3120 char c;
3121
3122 for (i=0; args[2][i]; i++) {
3123 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003124 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3125 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003126 break;
3127 }
3128
3129 if (!i || args[2][i]) {
3130 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3131 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3132 file, linenum, args[0], args[1]);
3133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
3135 }
3136 }
3137
3138 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3139 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3140 err_code |= ERR_ALERT | ERR_ABORT;
3141 goto out;
3142 }
3143 } else if (!strcmp(args[1], "show-desc")) {
3144 char *desc = NULL;
3145
3146 if (*args[2]) {
3147 int i, len=0;
3148 char *d;
3149
3150 for(i=2; *args[i]; i++)
3151 len += strlen(args[i])+1;
3152
3153 desc = d = (char *)calloc(1, len);
3154
3155 d += sprintf(d, "%s", args[2]);
3156 for(i=3; *args[i]; i++)
3157 d += sprintf(d, " %s", args[i]);
3158 }
3159
3160 if (!*args[2] && !global.desc)
3161 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3162 file, linenum, args[1]);
3163 else {
3164 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3165 free(desc);
3166 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3167 err_code |= ERR_ALERT | ERR_ABORT;
3168 goto out;
3169 }
3170 free(desc);
3171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003173stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003174 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 +01003175 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
3179 }
3180 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003181 int optnum;
3182
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003183 if (*(args[1]) == '\0') {
3184 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3185 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003189
3190 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3191 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003192 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3193 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3194 file, linenum, cfg_opts[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_opts[optnum].cap, file, linenum, args[1], NULL)) {
3199 err_code |= ERR_WARN;
3200 goto out;
3201 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003202
Willy Tarreau3842f002009-06-14 11:39:52 +02003203 curproxy->no_options &= ~cfg_opts[optnum].val;
3204 curproxy->options &= ~cfg_opts[optnum].val;
3205
3206 switch (kwm) {
3207 case KWM_STD:
3208 curproxy->options |= cfg_opts[optnum].val;
3209 break;
3210 case KWM_NO:
3211 curproxy->no_options |= cfg_opts[optnum].val;
3212 break;
3213 case KWM_DEF: /* already cleared */
3214 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003215 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003216
Willy Tarreau93893792009-07-23 13:19:11 +02003217 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003218 }
3219 }
3220
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003221 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3222 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003223 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3224 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3225 file, linenum, cfg_opts2[optnum].name);
3226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
3228 }
Willy Tarreau93893792009-07-23 13:19:11 +02003229 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3230 err_code |= ERR_WARN;
3231 goto out;
3232 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003233
Willy Tarreau3842f002009-06-14 11:39:52 +02003234 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3235 curproxy->options2 &= ~cfg_opts2[optnum].val;
3236
3237 switch (kwm) {
3238 case KWM_STD:
3239 curproxy->options2 |= cfg_opts2[optnum].val;
3240 break;
3241 case KWM_NO:
3242 curproxy->no_options2 |= cfg_opts2[optnum].val;
3243 break;
3244 case KWM_DEF: /* already cleared */
3245 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003246 }
Willy Tarreau93893792009-07-23 13:19:11 +02003247 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003248 }
3249 }
3250
Willy Tarreau3842f002009-06-14 11:39:52 +02003251 if (kwm != KWM_STD) {
3252 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003253 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003256 }
3257
Emeric Brun3a058f32009-06-30 18:26:00 +02003258 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003260 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003262 if (*(args[2]) != '\0') {
3263 if (!strcmp(args[2], "clf")) {
3264 curproxy->options2 |= PR_O2_CLFLOG;
3265 } else {
3266 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003269 }
3270 }
3271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 else if (!strcmp(args[1], "tcplog"))
3273 /* generate a detailed TCP log */
3274 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 else if (!strcmp(args[1], "tcpka")) {
3276 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003277 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003279
3280 if (curproxy->cap & PR_CAP_FE)
3281 curproxy->options |= PR_O_TCP_CLI_KA;
3282 if (curproxy->cap & PR_CAP_BE)
3283 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 }
3285 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_WARN;
3288
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003290 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003291 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003292 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003293 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003294 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003295 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003296 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003297 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 if (!*args[2]) { /* no argument */
3299 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3300 curproxy->check_len = strlen(DEF_CHECK_REQ);
3301 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003302 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 curproxy->check_req = (char *)malloc(reqlen);
3304 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003305 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003307 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 if (*args[4])
3309 reqlen += strlen(args[4]);
3310 else
3311 reqlen += strlen("HTTP/1.0");
3312
3313 curproxy->check_req = (char *)malloc(reqlen);
3314 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003315 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003317 }
3318 else if (!strcmp(args[1], "ssl-hello-chk")) {
3319 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003320 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003322
Willy Tarreaua534fea2008-08-03 12:19:50 +02003323 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003324 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003325 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003326 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003327 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003328 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003329 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003330 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 }
Willy Tarreau23677902007-05-08 23:50:35 +02003332 else if (!strcmp(args[1], "smtpchk")) {
3333 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003334 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003335 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003336 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003337 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003338 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003339 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003340 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003341 curproxy->options |= PR_O_SMTP_CHK;
3342
3343 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3344 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3345 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3346 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3347 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3348 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3349 curproxy->check_req = (char *)malloc(reqlen);
3350 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3351 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3352 } else {
3353 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3354 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3355 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3356 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3357 }
3358 }
3359 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003360 else if (!strcmp(args[1], "pgsql-check")) {
3361 /* use PostgreSQL request to check servers' health */
3362 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3363 err_code |= ERR_WARN;
3364
3365 free(curproxy->check_req);
3366 curproxy->check_req = NULL;
3367 curproxy->options &= ~PR_O_HTTP_CHK;
3368 curproxy->options &= ~PR_O_SMTP_CHK;
3369 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3370 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3371 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3372 curproxy->options2 |= PR_O2_PGSQL_CHK;
3373
3374 if (*(args[2])) {
3375 int cur_arg = 2;
3376
3377 while (*(args[cur_arg])) {
3378 if (strcmp(args[cur_arg], "user") == 0) {
3379 char * packet;
3380 uint32_t packet_len;
3381 uint32_t pv;
3382
3383 /* suboption header - needs additional argument for it */
3384 if (*(args[cur_arg+1]) == 0) {
3385 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3386 file, linenum, args[0], args[1], args[cur_arg]);
3387 err_code |= ERR_ALERT | ERR_FATAL;
3388 goto out;
3389 }
3390
3391 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3392 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3393 pv = htonl(0x30000); /* protocol version 3.0 */
3394
3395 packet = (char*) calloc(1, packet_len);
3396
3397 memcpy(packet + 4, &pv, 4);
3398
3399 /* copy "user" */
3400 memcpy(packet + 8, "user", 4);
3401
3402 /* copy username */
3403 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3404
3405 free(curproxy->check_req);
3406 curproxy->check_req = packet;
3407 curproxy->check_len = packet_len;
3408
3409 packet_len = htonl(packet_len);
3410 memcpy(packet, &packet_len, 4);
3411 cur_arg += 2;
3412 } else {
3413 /* unknown suboption - catchall */
3414 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3415 file, linenum, args[0], args[1]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419 } /* end while loop */
3420 }
3421 }
3422
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003423 else if (!strcmp(args[1], "mysql-check")) {
3424 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003425 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3426 err_code |= ERR_WARN;
3427
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003428 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003429 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003430 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003431 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003432 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003433 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003434 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003435 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003436
3437 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3438 * const char mysql40_client_auth_pkt[] = {
3439 * "\x0e\x00\x00" // packet length
3440 * "\x01" // packet number
3441 * "\x00\x00" // client capabilities
3442 * "\x00\x00\x01" // max packet
3443 * "haproxy\x00" // username (null terminated string)
3444 * "\x00" // filler (always 0x00)
3445 * "\x01\x00\x00" // packet length
3446 * "\x00" // packet number
3447 * "\x01" // COM_QUIT command
3448 * };
3449 */
3450
3451 if (*(args[2])) {
3452 int cur_arg = 2;
3453
3454 while (*(args[cur_arg])) {
3455 if (strcmp(args[cur_arg], "user") == 0) {
3456 char *mysqluser;
3457 int packetlen, reqlen, userlen;
3458
3459 /* suboption header - needs additional argument for it */
3460 if (*(args[cur_arg+1]) == 0) {
3461 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3462 file, linenum, args[0], args[1], args[cur_arg]);
3463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
3465 }
3466 mysqluser = args[cur_arg + 1];
3467 userlen = strlen(mysqluser);
3468 packetlen = userlen + 7;
3469 reqlen = packetlen + 9;
3470
3471 free(curproxy->check_req);
3472 curproxy->check_req = (char *)calloc(1, reqlen);
3473 curproxy->check_len = reqlen;
3474
3475 snprintf(curproxy->check_req, 4, "%c%c%c",
3476 ((unsigned char) packetlen & 0xff),
3477 ((unsigned char) (packetlen >> 8) & 0xff),
3478 ((unsigned char) (packetlen >> 16) & 0xff));
3479
3480 curproxy->check_req[3] = 1;
3481 curproxy->check_req[8] = 1;
3482 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3483 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3484 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3485 cur_arg += 2;
3486 } else {
3487 /* unknown suboption - catchall */
3488 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3489 file, linenum, args[0], args[1]);
3490 err_code |= ERR_ALERT | ERR_FATAL;
3491 goto out;
3492 }
3493 } /* end while loop */
3494 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003495 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003496 else if (!strcmp(args[1], "ldap-check")) {
3497 /* use LDAP request to check servers' health */
3498 free(curproxy->check_req);
3499 curproxy->check_req = NULL;
3500 curproxy->options &= ~PR_O_HTTP_CHK;
3501 curproxy->options &= ~PR_O_SMTP_CHK;
3502 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3503 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003504 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003505 curproxy->options2 |= PR_O2_LDAP_CHK;
3506
3507 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3508 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3509 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3510 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003511 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003512 int cur_arg;
3513
3514 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3515 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003516 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003517
3518 curproxy->options |= PR_O_FWDFOR;
3519
3520 free(curproxy->fwdfor_hdr_name);
3521 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3522 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3523
3524 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3525 cur_arg = 2;
3526 while (*(args[cur_arg])) {
3527 if (!strcmp(args[cur_arg], "except")) {
3528 /* suboption except - needs additional argument for it */
3529 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3530 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3531 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003534 }
3535 /* flush useless bits */
3536 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003537 cur_arg += 2;
3538 } else if (!strcmp(args[cur_arg], "header")) {
3539 /* suboption header - needs additional argument for it */
3540 if (*(args[cur_arg+1]) == 0) {
3541 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3542 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003545 }
3546 free(curproxy->fwdfor_hdr_name);
3547 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3548 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3549 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003550 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003551 /* unknown suboption - catchall */
3552 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3553 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003554 err_code |= ERR_ALERT | ERR_FATAL;
3555 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003556 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003557 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003558 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003559 else if (!strcmp(args[1], "originalto")) {
3560 int cur_arg;
3561
3562 /* insert x-original-to field, but not for the IP address listed as an except.
3563 * set default options (ie: bitfield, header name, etc)
3564 */
3565
3566 curproxy->options |= PR_O_ORGTO;
3567
3568 free(curproxy->orgto_hdr_name);
3569 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3570 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3571
3572 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3573 cur_arg = 2;
3574 while (*(args[cur_arg])) {
3575 if (!strcmp(args[cur_arg], "except")) {
3576 /* suboption except - needs additional argument for it */
3577 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3578 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3579 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003582 }
3583 /* flush useless bits */
3584 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3585 cur_arg += 2;
3586 } else if (!strcmp(args[cur_arg], "header")) {
3587 /* suboption header - needs additional argument for it */
3588 if (*(args[cur_arg+1]) == 0) {
3589 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3590 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003593 }
3594 free(curproxy->orgto_hdr_name);
3595 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3596 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3597 cur_arg += 2;
3598 } else {
3599 /* unknown suboption - catchall */
3600 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3601 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003602 err_code |= ERR_ALERT | ERR_FATAL;
3603 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003604 }
3605 } /* end while loop */
3606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 else {
3608 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003609 err_code |= ERR_ALERT | ERR_FATAL;
3610 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003611 }
Willy Tarreau93893792009-07-23 13:19:11 +02003612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003614 else if (!strcmp(args[0], "default_backend")) {
3615 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003617
3618 if (*(args[1]) == 0) {
3619 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003620 err_code |= ERR_ALERT | ERR_FATAL;
3621 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003622 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003623 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003624 curproxy->defbe.name = strdup(args[1]);
3625 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003626 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003627 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003629
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003630 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3631 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003632 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 /* enable reconnections to dispatch */
3634 curproxy->options |= PR_O_REDISP;
3635 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003636 else if (!strcmp(args[0], "http-check")) {
3637 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003639
3640 if (strcmp(args[1], "disable-on-404") == 0) {
3641 /* enable a graceful server shutdown on an HTTP 404 response */
3642 curproxy->options |= PR_O_DISABLE404;
3643 }
Willy Tarreauef781042010-01-27 11:53:01 +01003644 else if (strcmp(args[1], "send-state") == 0) {
3645 /* enable emission of the apparent state of a server in HTTP checks */
3646 curproxy->options2 |= PR_O2_CHK_SNDST;
3647 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003648 else if (strcmp(args[1], "expect") == 0) {
3649 const char *ptr_arg;
3650 int cur_arg;
3651
3652 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3653 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
3656 }
3657
3658 cur_arg = 2;
3659 /* consider exclamation marks, sole or at the beginning of a word */
3660 while (*(ptr_arg = args[cur_arg])) {
3661 while (*ptr_arg == '!') {
3662 curproxy->options2 ^= PR_O2_EXP_INV;
3663 ptr_arg++;
3664 }
3665 if (*ptr_arg)
3666 break;
3667 cur_arg++;
3668 }
3669 /* now ptr_arg points to the beginning of a word past any possible
3670 * exclamation mark, and cur_arg is the argument which holds this word.
3671 */
3672 if (strcmp(ptr_arg, "status") == 0) {
3673 if (!*(args[cur_arg + 1])) {
3674 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3675 file, linenum, args[0], args[1], ptr_arg);
3676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
3678 }
3679 curproxy->options2 |= PR_O2_EXP_STS;
3680 curproxy->expect_str = strdup(args[cur_arg + 1]);
3681 }
3682 else if (strcmp(ptr_arg, "string") == 0) {
3683 if (!*(args[cur_arg + 1])) {
3684 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3685 file, linenum, args[0], args[1], ptr_arg);
3686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
3688 }
3689 curproxy->options2 |= PR_O2_EXP_STR;
3690 curproxy->expect_str = strdup(args[cur_arg + 1]);
3691 }
3692 else if (strcmp(ptr_arg, "rstatus") == 0) {
3693 if (!*(args[cur_arg + 1])) {
3694 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3695 file, linenum, args[0], args[1], ptr_arg);
3696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
3698 }
3699 curproxy->options2 |= PR_O2_EXP_RSTS;
3700 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3701 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3702 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3703 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
3706 }
3707 }
3708 else if (strcmp(ptr_arg, "rstring") == 0) {
3709 if (!*(args[cur_arg + 1])) {
3710 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3711 file, linenum, args[0], args[1], ptr_arg);
3712 err_code |= ERR_ALERT | ERR_FATAL;
3713 goto out;
3714 }
3715 curproxy->options2 |= PR_O2_EXP_RSTR;
3716 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3717 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3718 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3719 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723 }
3724 else {
3725 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3726 file, linenum, args[0], args[1], ptr_arg);
3727 err_code |= ERR_ALERT | ERR_FATAL;
3728 goto out;
3729 }
3730 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003731 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003732 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003735 }
3736 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003737 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003738 if (curproxy == &defproxy) {
3739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003742 }
3743
Willy Tarreaub80c2302007-11-30 20:51:32 +01003744 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003746
3747 if (strcmp(args[1], "fail") == 0) {
3748 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003749 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003750 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3751 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003754 }
3755
Willy Tarreauef6494c2010-01-28 17:12:36 +01003756 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003757 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3758 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003761 }
3762 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3763 }
3764 else {
3765 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003768 }
3769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770#ifdef TPROXY
3771 else if (!strcmp(args[0], "transparent")) {
3772 /* enable transparent proxy connections */
3773 curproxy->options |= PR_O_TRANSP;
3774 }
3775#endif
3776 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003777 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003779
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 if (*(args[1]) == 0) {
3781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 }
3785 curproxy->maxconn = atol(args[1]);
3786 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003787 else if (!strcmp(args[0], "backlog")) { /* backlog */
3788 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003790
3791 if (*(args[1]) == 0) {
3792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003795 }
3796 curproxy->backlog = atol(args[1]);
3797 }
Willy Tarreau86034312006-12-29 00:10:33 +01003798 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003799 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003801
Willy Tarreau86034312006-12-29 00:10:33 +01003802 if (*(args[1]) == 0) {
3803 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003806 }
3807 curproxy->fullconn = atol(args[1]);
3808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3810 if (*(args[1]) == 0) {
3811 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003814 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003815 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3816 if (err) {
3817 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3818 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003821 }
3822 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
3824 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003825 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 if (curproxy == &defproxy) {
3827 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003830 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003831 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003833
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 if (strchr(args[1], ':') == NULL) {
3835 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003836 err_code |= ERR_ALERT | ERR_FATAL;
3837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003838 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003839 sk = str2sa(args[1]);
3840 if (!sk) {
3841 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
3844 }
3845 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003846 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 }
3848 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003849 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003851
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003852 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003853 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3854 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003859 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3860 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3861 err_code |= ERR_WARN;
3862
3863 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3864 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3865 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3866 }
3867 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3868 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3869 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3870 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003871 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3872 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3873 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3874 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003875 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003876 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
3879 }
3880 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003881 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003882 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003883 char *rport, *raddr;
3884 short realport = 0;
3885 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003886
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003887 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003889 err_code |= ERR_ALERT | ERR_FATAL;
3890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003892 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894
3895 if (!*args[2]) {
3896 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3897 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003901
3902 err = invalid_char(args[1]);
3903 if (err) {
3904 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3905 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003908 }
3909
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003910 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003911 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003912
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003913 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3914 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3915 err_code |= ERR_ALERT | ERR_ABORT;
3916 goto out;
3917 }
3918
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003919 /* the servers are linked backwards first */
3920 newsrv->next = curproxy->srv;
3921 curproxy->srv = newsrv;
3922 newsrv->proxy = curproxy;
3923 newsrv->conf.file = file;
3924 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003926 LIST_INIT(&newsrv->pendconns);
3927 do_check = 0;
3928 newsrv->state = SRV_RUNNING; /* early server setup */
3929 newsrv->last_change = now.tv_sec;
3930 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003932 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003933 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003934 * - IP: => port=+0, relative
3935 * - IP:N => port=N, absolute
3936 * - IP:+N => port=+N, relative
3937 * - IP:-N => port=-N, relative
3938 */
3939 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003940 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003941 if (rport) {
3942 *rport++ = 0;
3943 realport = atol(rport);
3944 if (!isdigit((unsigned char)*rport))
3945 newsrv->state |= SRV_MAPPORTS;
3946 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003948
Willy Tarreaufab5a432011-03-04 15:31:53 +01003949 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003950 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003951 if (!sk) {
3952 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
3955 }
3956 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003957
3958 switch (newsrv->addr.ss_family) {
3959 case AF_INET:
3960 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3961 break;
3962 case AF_INET6:
3963 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3964 break;
3965 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003966
3967 newsrv->check_port = curproxy->defsrv.check_port;
3968 newsrv->inter = curproxy->defsrv.inter;
3969 newsrv->fastinter = curproxy->defsrv.fastinter;
3970 newsrv->downinter = curproxy->defsrv.downinter;
3971 newsrv->rise = curproxy->defsrv.rise;
3972 newsrv->fall = curproxy->defsrv.fall;
3973 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3974 newsrv->minconn = curproxy->defsrv.minconn;
3975 newsrv->maxconn = curproxy->defsrv.maxconn;
3976 newsrv->slowstart = curproxy->defsrv.slowstart;
3977 newsrv->onerror = curproxy->defsrv.onerror;
3978 newsrv->consecutive_errors_limit
3979 = curproxy->defsrv.consecutive_errors_limit;
3980 newsrv->uweight = newsrv->iweight
3981 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003983 newsrv->curfd = -1; /* no health-check in progress */
3984 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003986 cur_arg = 3;
3987 } else {
3988 newsrv = &curproxy->defsrv;
3989 cur_arg = 1;
3990 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003991
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003993 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003994 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003995
3996 if (!*args[cur_arg + 1]) {
3997 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3998 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004001 }
4002
4003 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004004 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004005
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004006 if (newsrv->puid <= 0) {
4007 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004008 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004011 }
4012
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004013 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4014 if (node) {
4015 struct server *target = container_of(node, struct server, conf.id);
4016 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4017 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004022 cur_arg += 2;
4023 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004024 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 newsrv->cookie = strdup(args[cur_arg + 1]);
4026 newsrv->cklen = strlen(args[cur_arg + 1]);
4027 cur_arg += 2;
4028 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004029 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004030 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4031 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4032 cur_arg += 2;
4033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004035 if (!*args[cur_arg + 1]) {
4036 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4037 file, linenum, args[cur_arg]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041
Willy Tarreaubaaee002006-06-26 02:48:02 +02004042 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004043 if (newsrv->rise <= 0) {
4044 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4045 file, linenum, args[cur_arg]);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049
Willy Tarreau96839092010-03-29 10:02:24 +02004050 if (newsrv->health)
4051 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 cur_arg += 2;
4053 }
4054 else if (!strcmp(args[cur_arg], "fall")) {
4055 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004056
4057 if (!*args[cur_arg + 1]) {
4058 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4059 file, linenum, args[cur_arg]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063
4064 if (newsrv->fall <= 0) {
4065 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4066 file, linenum, args[cur_arg]);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070
Willy Tarreaubaaee002006-06-26 02:48:02 +02004071 cur_arg += 2;
4072 }
4073 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004074 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4075 if (err) {
4076 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4077 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004080 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004081 if (val <= 0) {
4082 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4083 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004086 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004087 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004088 cur_arg += 2;
4089 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004090 else if (!strcmp(args[cur_arg], "fastinter")) {
4091 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4092 if (err) {
4093 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4094 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004097 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004098 if (val <= 0) {
4099 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4100 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004103 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004104 newsrv->fastinter = val;
4105 cur_arg += 2;
4106 }
4107 else if (!strcmp(args[cur_arg], "downinter")) {
4108 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4109 if (err) {
4110 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4111 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004114 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004115 if (val <= 0) {
4116 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4117 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004118 err_code |= ERR_ALERT | ERR_FATAL;
4119 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004120 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004121 newsrv->downinter = val;
4122 cur_arg += 2;
4123 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004124 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004125 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004126 if (!sk) {
4127 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004132 cur_arg += 2;
4133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004134 else if (!strcmp(args[cur_arg], "port")) {
4135 newsrv->check_port = atol(args[cur_arg + 1]);
4136 cur_arg += 2;
4137 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004138 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004139 newsrv->state |= SRV_BACKUP;
4140 cur_arg ++;
4141 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004142 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4143 newsrv->state |= SRV_SEND_PROXY;
4144 cur_arg ++;
4145 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 else if (!strcmp(args[cur_arg], "weight")) {
4147 int w;
4148 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004149 if (w < 0 || w > 256) {
4150 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004154 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004155 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 cur_arg += 2;
4157 }
4158 else if (!strcmp(args[cur_arg], "minconn")) {
4159 newsrv->minconn = atol(args[cur_arg + 1]);
4160 cur_arg += 2;
4161 }
4162 else if (!strcmp(args[cur_arg], "maxconn")) {
4163 newsrv->maxconn = atol(args[cur_arg + 1]);
4164 cur_arg += 2;
4165 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004166 else if (!strcmp(args[cur_arg], "maxqueue")) {
4167 newsrv->maxqueue = atol(args[cur_arg + 1]);
4168 cur_arg += 2;
4169 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004170 else if (!strcmp(args[cur_arg], "slowstart")) {
4171 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004172 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004173 if (err) {
4174 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4175 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004178 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004179 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004180 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4181 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004184 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004185 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004186 cur_arg += 2;
4187 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004188 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004189
4190 if (!*args[cur_arg + 1]) {
4191 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4192 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004195 }
4196
4197 newsrv->trackit = strdup(args[cur_arg + 1]);
4198
4199 cur_arg += 2;
4200 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004201 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 global.maxsock++;
4203 do_check = 1;
4204 cur_arg += 1;
4205 }
Willy Tarreau96839092010-03-29 10:02:24 +02004206 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4207 newsrv->state |= SRV_MAINTAIN;
4208 newsrv->state &= ~SRV_RUNNING;
4209 newsrv->health = 0;
4210 cur_arg += 1;
4211 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004212 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004213 if (!strcmp(args[cur_arg + 1], "none"))
4214 newsrv->observe = HANA_OBS_NONE;
4215 else if (!strcmp(args[cur_arg + 1], "layer4"))
4216 newsrv->observe = HANA_OBS_LAYER4;
4217 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4218 if (curproxy->mode != PR_MODE_HTTP) {
4219 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4220 file, linenum, args[cur_arg + 1]);
4221 err_code |= ERR_ALERT;
4222 }
4223 newsrv->observe = HANA_OBS_LAYER7;
4224 }
4225 else {
4226 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004227 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004228 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 }
4235 else if (!strcmp(args[cur_arg], "on-error")) {
4236 if (!strcmp(args[cur_arg + 1], "fastinter"))
4237 newsrv->onerror = HANA_ONERR_FASTINTER;
4238 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4239 newsrv->onerror = HANA_ONERR_FAILCHK;
4240 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4241 newsrv->onerror = HANA_ONERR_SUDDTH;
4242 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4243 newsrv->onerror = HANA_ONERR_MARKDWN;
4244 else {
4245 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004246 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004247 file, linenum, args[cur_arg], args[cur_arg + 1]);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251
4252 cur_arg += 2;
4253 }
4254 else if (!strcmp(args[cur_arg], "error-limit")) {
4255 if (!*args[cur_arg + 1]) {
4256 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4257 file, linenum, args[cur_arg]);
4258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
4260 }
4261
4262 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4263
4264 if (newsrv->consecutive_errors_limit <= 0) {
4265 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4266 file, linenum, args[cur_arg]);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004270 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004271 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004272 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004273 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004274 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004275
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004277#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004278 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004279 file, linenum, "source", "usesrc");
4280#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004281 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004282 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004283#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 }
4287 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004288 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4289 if (!sk) {
4290 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004295
4296 if (port_low != port_high) {
4297 int i;
4298 if (port_low <= 0 || port_low > 65535 ||
4299 port_high <= 0 || port_high > 65535 ||
4300 port_low > port_high) {
4301 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4302 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004305 }
4306 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4307 for (i = 0; i < newsrv->sport_range->size; i++)
4308 newsrv->sport_range->ports[i] = port_low + i;
4309 }
4310
Willy Tarreaubaaee002006-06-26 02:48:02 +02004311 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004312 while (*(args[cur_arg])) {
4313 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004314#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4315#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004316 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4317 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4318 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004321 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004322#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004323 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004324 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 }
4329 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004330 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004331 newsrv->state |= SRV_TPROXY_CLI;
4332 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004333 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004334 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004335 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4336 char *name, *end;
4337
4338 name = args[cur_arg+1] + 7;
4339 while (isspace(*name))
4340 name++;
4341
4342 end = name;
4343 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4344 end++;
4345
4346 newsrv->state &= ~SRV_TPROXY_MASK;
4347 newsrv->state |= SRV_TPROXY_DYN;
4348 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4349 newsrv->bind_hdr_len = end - name;
4350 memcpy(newsrv->bind_hdr_name, name, end - name);
4351 newsrv->bind_hdr_name[end-name] = '\0';
4352 newsrv->bind_hdr_occ = -1;
4353
4354 /* now look for an occurrence number */
4355 while (isspace(*end))
4356 end++;
4357 if (*end == ',') {
4358 end++;
4359 name = end;
4360 if (*end == '-')
4361 end++;
4362 while (isdigit(*end))
4363 end++;
4364 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4365 }
4366
4367 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4368 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4369 " occurrences values smaller than %d.\n",
4370 file, linenum, MAX_HDR_HISTORY);
4371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
4373 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004374 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004375 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004376 if (!sk) {
4377 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
4380 }
4381 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004382 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 }
4384 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004385#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004386 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004387#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004388 cur_arg += 2;
4389 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004390#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004391 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004392 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004395#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4396 } /* "usesrc" */
4397
4398 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4399#ifdef SO_BINDTODEVICE
4400 if (!*args[cur_arg + 1]) {
4401 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4402 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004405 }
4406 if (newsrv->iface_name)
4407 free(newsrv->iface_name);
4408
4409 newsrv->iface_name = strdup(args[cur_arg + 1]);
4410 newsrv->iface_len = strlen(newsrv->iface_name);
4411 global.last_checks |= LSTCHK_NETADM;
4412#else
4413 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4414 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004417#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004418 cur_arg += 2;
4419 continue;
4420 }
4421 /* this keyword in not an option of "source" */
4422 break;
4423 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004424 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004425 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004426 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4427 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004431 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004432 if (!defsrv)
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004433 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', '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 +01004434 file, linenum, newsrv->id);
4435 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004436 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 +01004437 file, linenum);
4438
Willy Tarreau93893792009-07-23 13:19:11 +02004439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441 }
4442 }
4443
4444 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004445 if (newsrv->trackit) {
4446 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4447 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004450 }
4451
David du Colombier6f5ccb12011-03-10 22:26:24 +01004452 switch (newsrv->check_addr.ss_family) {
4453 case AF_INET:
4454 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4455 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4456 break;
4457 case AF_INET6:
4458 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4459 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4460 break;
4461 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004462
Willy Tarreaubaaee002006-06-26 02:48:02 +02004463 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4464 newsrv->check_port = realport; /* by default */
4465 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004466 /* not yet valid, because no port was set on
4467 * the server either. We'll check if we have
4468 * a known port on the first listener.
4469 */
4470 struct listener *l;
4471 l = curproxy->listen;
4472 if (l) {
4473 int port;
4474 port = (l->addr.ss_family == AF_INET6)
4475 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4476 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4477 newsrv->check_port = port;
4478 }
4479 }
4480 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4482 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004483 err_code |= ERR_ALERT | ERR_FATAL;
4484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004485 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004486
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004487 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004488 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004489 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4490 err_code |= ERR_ALERT | ERR_ABORT;
4491 goto out;
4492 }
4493
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004494 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 newsrv->state |= SRV_CHECKED;
4496 }
4497
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004498 if (!defsrv) {
4499 if (newsrv->state & SRV_BACKUP)
4500 curproxy->srv_bck++;
4501 else
4502 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004503
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004504 newsrv->prev_state = newsrv->state;
4505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 }
4507 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004508 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 int facility;
4510
4511 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4512 curproxy->logfac1 = global.logfac1;
4513 curproxy->logsrv1 = global.logsrv1;
4514 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004515 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 curproxy->logfac2 = global.logfac2;
4517 curproxy->logsrv2 = global.logsrv2;
4518 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004519 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 }
4521 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004522 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523
4524 facility = get_log_facility(args[2]);
4525 if (facility < 0) {
4526 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4527 exit(1);
4528 }
4529
4530 level = 7; /* max syslog level = debug */
4531 if (*(args[3])) {
4532 level = get_log_level(args[3]);
4533 if (level < 0) {
4534 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4535 exit(1);
4536 }
4537 }
4538
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004539 minlvl = 0; /* limit syslog level to this level (emerg) */
4540 if (*(args[4])) {
4541 minlvl = get_log_level(args[4]);
4542 if (level < 0) {
4543 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4544 exit(1);
4545 }
4546 }
4547
Robert Tsai81ae1952007-12-05 10:47:29 +01004548 if (args[1][0] == '/') {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004549 struct sockaddr_un *sk = str2sun(args[1]);
4550 if (!sk) {
4551 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
4552 args[1], (int)sizeof(sk->sun_path) - 1);
4553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
4555 }
4556 logsrv.u.un = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004557 logsrv.u.addr.sa_family = AF_UNIX;
Robert Tsai81ae1952007-12-05 10:47:29 +01004558 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004559 struct sockaddr_storage *sk = str2sa(args[1]);
4560 if (!sk || sk->ss_family != AF_INET) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004561 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
4564 }
David du Colombier6f5ccb12011-03-10 22:26:24 +01004565 logsrv.u.in = *(struct sockaddr_in *)sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004566 logsrv.u.addr.sa_family = AF_INET;
Robert Tsai81ae1952007-12-05 10:47:29 +01004567 if (!logsrv.u.in.sin_port) {
4568 logsrv.u.in.sin_port =
4569 htons(SYSLOG_PORT);
4570 }
4571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572
4573 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004574 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 curproxy->logfac1 = facility;
4576 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004577 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 }
4579 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004580 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 curproxy->logfac2 = facility;
4582 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004583 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004584 }
4585 else {
4586 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004587 err_code |= ERR_ALERT | ERR_FATAL;
4588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 }
4590 }
4591 else {
4592 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4593 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 }
4597 }
4598 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004599 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004600 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004601
Willy Tarreau977b8e42006-12-29 14:19:17 +01004602 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004604
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004606 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4607 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004611
4612 /* we must first clear any optional default setting */
4613 curproxy->options &= ~PR_O_TPXY_MASK;
4614 free(curproxy->iface_name);
4615 curproxy->iface_name = NULL;
4616 curproxy->iface_len = 0;
4617
Willy Tarreaud5191e72010-02-09 20:50:45 +01004618 sk = str2sa(args[1]);
4619 if (!sk) {
4620 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
4623 }
4624 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004626
4627 cur_arg = 2;
4628 while (*(args[cur_arg])) {
4629 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004630#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4631#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004632 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4633 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4634 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004637 }
4638#endif
4639 if (!*args[cur_arg + 1]) {
4640 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4641 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004644 }
4645
4646 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004647 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004648 curproxy->options |= PR_O_TPXY_CLI;
4649 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004650 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004651 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004652 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4653 char *name, *end;
4654
4655 name = args[cur_arg+1] + 7;
4656 while (isspace(*name))
4657 name++;
4658
4659 end = name;
4660 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4661 end++;
4662
4663 curproxy->options &= ~PR_O_TPXY_MASK;
4664 curproxy->options |= PR_O_TPXY_DYN;
4665 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4666 curproxy->bind_hdr_len = end - name;
4667 memcpy(curproxy->bind_hdr_name, name, end - name);
4668 curproxy->bind_hdr_name[end-name] = '\0';
4669 curproxy->bind_hdr_occ = -1;
4670
4671 /* now look for an occurrence number */
4672 while (isspace(*end))
4673 end++;
4674 if (*end == ',') {
4675 end++;
4676 name = end;
4677 if (*end == '-')
4678 end++;
4679 while (isdigit(*end))
4680 end++;
4681 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4682 }
4683
4684 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4685 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4686 " occurrences values smaller than %d.\n",
4687 file, linenum, MAX_HDR_HISTORY);
4688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004691 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004692 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004693 if (!sk) {
4694 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
4697 }
4698 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004699 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700 }
4701 global.last_checks |= LSTCHK_NETADM;
4702#if !defined(CONFIG_HAP_LINUX_TPROXY)
4703 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004704#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004705#else /* no TPROXY support */
4706 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004707 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004710#endif
4711 cur_arg += 2;
4712 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004713 }
4714
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4716#ifdef SO_BINDTODEVICE
4717 if (!*args[cur_arg + 1]) {
4718 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4719 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004722 }
4723 if (curproxy->iface_name)
4724 free(curproxy->iface_name);
4725
4726 curproxy->iface_name = strdup(args[cur_arg + 1]);
4727 curproxy->iface_len = strlen(curproxy->iface_name);
4728 global.last_checks |= LSTCHK_NETADM;
4729#else
4730 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4731 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004734#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004735 cur_arg += 2;
4736 continue;
4737 }
4738 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4739 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004744 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4745 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4746 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004750 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004751 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4753 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004757
4758 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4759 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004760 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004761 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
4764 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004765 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4766 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004767 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004768 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 }
4771 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4773 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004774 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004775 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004777 }
4778 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4780 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004781 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004782 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 }
4785 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4787 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004788 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004791 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004792 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4794 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004795 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004797 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004798 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004799 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4801 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004802 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004803 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004804 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004805 }
4806 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004807 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4808 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004809 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004810 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004811 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004812 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004813 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004814 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4816 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004820
4821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4822 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004823 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004826 }
4827 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4829 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004830 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004831 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004833 }
4834 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4836 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004837 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004838 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 }
4841 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4843 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004844 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004845 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 }
4848 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4850 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004851 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004852 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004854 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004855 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004856 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4857 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004858 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004859 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004860 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004863 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004864
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 if (curproxy == &defproxy) {
4866 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004867 err_code |= ERR_ALERT | ERR_FATAL;
4868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004870 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004871 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 if (*(args[1]) == 0) {
4874 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004878
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004879 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4880 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4881 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4882 file, linenum, args[0]);
4883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
4885 }
4886 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4887 }
4888 else if (*args[2]) {
4889 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4890 file, linenum, args[0], args[2]);
4891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893 }
4894
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004895 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004896 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004897 wl->s = strdup(args[1]);
4898 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004899 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
4901 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4904 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004908
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4910 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004911 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 }
4915 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004916 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4917 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004918 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 }
4922 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4924 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004925 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
4929 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4932 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
4936
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4938 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004939 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 }
4943 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4945 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004946 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 }
4950 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004951 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4952 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004953 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
4957 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004958 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004959
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 if (curproxy == &defproxy) {
4961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004965 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 if (*(args[1]) == 0) {
4969 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\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
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004974 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4975 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4976 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4977 file, linenum, args[0]);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981 err_code |= warnif_cond_requires_req(cond, file, linenum);
4982 }
4983 else if (*args[2]) {
4984 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4985 file, linenum, args[0], args[2]);
4986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
4988 }
4989
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004990 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004991 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004992 wl->s = strdup(args[1]);
4993 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
4995 else if (!strcmp(args[0], "errorloc") ||
4996 !strcmp(args[0], "errorloc302") ||
4997 !strcmp(args[0], "errorloc303")) { /* error location */
4998 int errnum, errlen;
4999 char *err;
5000
Willy Tarreau977b8e42006-12-29 14:19:17 +01005001 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005003
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005005 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
5009
5010 errnum = atol(args[1]);
5011 if (!strcmp(args[0], "errorloc303")) {
5012 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5013 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5014 } else {
5015 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5016 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5017 }
5018
Willy Tarreau0f772532006-12-23 20:51:41 +01005019 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5020 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005021 chunk_destroy(&curproxy->errmsg[rc]);
5022 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005023 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005026
5027 if (rc >= HTTP_ERR_SIZE) {
5028 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5029 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 free(err);
5031 }
5032 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005033 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5034 int errnum, errlen, fd;
5035 char *err;
5036 struct stat stat;
5037
5038 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005040
5041 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005042 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005045 }
5046
5047 fd = open(args[2], O_RDONLY);
5048 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5049 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5050 file, linenum, args[2], args[1]);
5051 if (fd >= 0)
5052 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005055 }
5056
Willy Tarreau27a674e2009-08-17 07:23:33 +02005057 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005058 errlen = stat.st_size;
5059 } else {
5060 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005061 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005063 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005064 }
5065
5066 err = malloc(errlen); /* malloc() must succeed during parsing */
5067 errnum = read(fd, err, errlen);
5068 if (errnum != errlen) {
5069 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5070 file, linenum, args[2], args[1]);
5071 close(fd);
5072 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005075 }
5076 close(fd);
5077
5078 errnum = atol(args[1]);
5079 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5080 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005081 chunk_destroy(&curproxy->errmsg[rc]);
5082 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005083 break;
5084 }
5085 }
5086
5087 if (rc >= HTTP_ERR_SIZE) {
5088 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5089 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005090 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005091 free(err);
5092 }
5093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005095 struct cfg_kw_list *kwl;
5096 int index;
5097
5098 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5099 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5100 if (kwl->kw[index].section != CFG_LISTEN)
5101 continue;
5102 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5103 /* prepare error message just in case */
5104 snprintf(trash, sizeof(trash),
5105 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005106 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5107 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005108 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005111 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005112 else if (rc > 0) {
5113 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_WARN;
5115 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005116 }
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005118 }
5119 }
5120 }
5121
Willy Tarreau6daf3432008-01-22 16:44:08 +01005122 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
Willy Tarreau93893792009-07-23 13:19:11 +02005126 out:
5127 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128}
5129
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005130int
5131cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5132{
5133
5134 int err_code = 0;
5135 const char *err;
5136
5137 if (!strcmp(args[0], "userlist")) { /* new userlist */
5138 struct userlist *newul;
5139
5140 if (!*args[1]) {
5141 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5142 file, linenum, args[0]);
5143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
5145 }
5146
5147 err = invalid_char(args[1]);
5148 if (err) {
5149 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5150 file, linenum, *err, args[0], args[1]);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
5154
5155 for (newul = userlist; newul; newul = newul->next)
5156 if (!strcmp(newul->name, args[1])) {
5157 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5158 file, linenum, args[1]);
5159 err_code |= ERR_WARN;
5160 goto out;
5161 }
5162
5163 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5164 if (!newul) {
5165 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5166 err_code |= ERR_ALERT | ERR_ABORT;
5167 goto out;
5168 }
5169
5170 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5171 newul->name = strdup(args[1]);
5172
5173 if (!newul->groupusers | !newul->name) {
5174 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5175 err_code |= ERR_ALERT | ERR_ABORT;
5176 goto out;
5177 }
5178
5179 newul->next = userlist;
5180 userlist = newul;
5181
5182 } else if (!strcmp(args[0], "group")) { /* new group */
5183 int cur_arg, i;
5184 const char *err;
5185
5186 if (!*args[1]) {
5187 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5188 file, linenum, args[0]);
5189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
5191 }
5192
5193 err = invalid_char(args[1]);
5194 if (err) {
5195 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5196 file, linenum, *err, args[0], args[1]);
5197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
5199 }
5200
5201 for(i = 0; i < userlist->grpcnt; i++)
5202 if (!strcmp(userlist->groups[i], args[1])) {
5203 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5204 file, linenum, args[1], userlist->name);
5205 err_code |= ERR_ALERT;
5206 goto out;
5207 }
5208
5209 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5210 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5211 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5212 err_code |= ERR_ALERT | ERR_FATAL;
5213 goto out;
5214 }
5215
5216 cur_arg = 2;
5217
5218 while (*args[cur_arg]) {
5219 if (!strcmp(args[cur_arg], "users")) {
5220 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5221 cur_arg += 2;
5222 continue;
5223 } else {
5224 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5225 file, linenum, args[0]);
5226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
5228 }
5229 }
5230
5231 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5232 } else if (!strcmp(args[0], "user")) { /* new user */
5233 struct auth_users *newuser;
5234 int cur_arg;
5235
5236 if (!*args[1]) {
5237 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5238 file, linenum, args[0]);
5239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
5241 }
5242
5243 for (newuser = userlist->users; newuser; newuser = newuser->next)
5244 if (!strcmp(newuser->user, args[1])) {
5245 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5246 file, linenum, args[1], userlist->name);
5247 err_code |= ERR_ALERT;
5248 goto out;
5249 }
5250
5251 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5252 if (!newuser) {
5253 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5254 err_code |= ERR_ALERT | ERR_ABORT;
5255 goto out;
5256 }
5257
5258 newuser->user = strdup(args[1]);
5259
5260 newuser->next = userlist->users;
5261 userlist->users = newuser;
5262
5263 cur_arg = 2;
5264
5265 while (*args[cur_arg]) {
5266 if (!strcmp(args[cur_arg], "password")) {
5267#ifndef CONFIG_HAP_CRYPT
5268 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5269 file, linenum);
5270 err_code |= ERR_ALERT;
5271#endif
5272 newuser->pass = strdup(args[cur_arg + 1]);
5273 cur_arg += 2;
5274 continue;
5275 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5276 newuser->pass = strdup(args[cur_arg + 1]);
5277 newuser->flags |= AU_O_INSECURE;
5278 cur_arg += 2;
5279 continue;
5280 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005281 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005282 cur_arg += 2;
5283 continue;
5284 } else {
5285 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5286 file, linenum, args[0]);
5287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
5289 }
5290 }
5291 } else {
5292 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 }
5295
5296out:
5297 return err_code;
5298}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299
5300/*
5301 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005302 * Returns the error code, 0 if OK, or any combination of :
5303 * - ERR_ABORT: must abort ASAP
5304 * - ERR_FATAL: we can continue parsing but not start the service
5305 * - ERR_WARN: a warning has been emitted
5306 * - ERR_ALERT: an alert has been emitted
5307 * Only the two first ones can stop processing, the two others are just
5308 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005310int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005312 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 FILE *f;
5314 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005316 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005317
Willy Tarreaubaaee002006-06-26 02:48:02 +02005318 if ((f=fopen(file,"r")) == NULL)
5319 return -1;
5320
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005321 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005322 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005323 char *end;
5324 char *args[MAX_LINE_ARGS + 1];
5325 char *line = thisline;
5326
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 linenum++;
5328
5329 end = line + strlen(line);
5330
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005331 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5332 /* Check if we reached the limit and the last char is not \n.
5333 * Watch out for the last line without the terminating '\n'!
5334 */
5335 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005336 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005337 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005338 }
5339
Willy Tarreaubaaee002006-06-26 02:48:02 +02005340 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005341 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 line++;
5343
5344 arg = 0;
5345 args[arg] = line;
5346
5347 while (*line && arg < MAX_LINE_ARGS) {
5348 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5349 * C equivalent value. Other combinations left unchanged (eg: \1).
5350 */
5351 if (*line == '\\') {
5352 int skip = 0;
5353 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5354 *line = line[1];
5355 skip = 1;
5356 }
5357 else if (line[1] == 'r') {
5358 *line = '\r';
5359 skip = 1;
5360 }
5361 else if (line[1] == 'n') {
5362 *line = '\n';
5363 skip = 1;
5364 }
5365 else if (line[1] == 't') {
5366 *line = '\t';
5367 skip = 1;
5368 }
5369 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005370 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 unsigned char hex1, hex2;
5372 hex1 = toupper(line[2]) - '0';
5373 hex2 = toupper(line[3]) - '0';
5374 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5375 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5376 *line = (hex1<<4) + hex2;
5377 skip = 3;
5378 }
5379 else {
5380 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005381 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
5383 }
5384 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005385 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005386 end -= skip;
5387 }
5388 line++;
5389 }
5390 else if (*line == '#' || *line == '\n' || *line == '\r') {
5391 /* end of string, end of loop */
5392 *line = 0;
5393 break;
5394 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005395 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005397 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005398 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005399 line++;
5400 args[++arg] = line;
5401 }
5402 else {
5403 line++;
5404 }
5405 }
5406
5407 /* empty line */
5408 if (!**args)
5409 continue;
5410
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005411 if (*line) {
5412 /* we had to stop due to too many args.
5413 * Let's terminate the string, print the offending part then cut the
5414 * last arg.
5415 */
5416 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5417 line++;
5418 *line = '\0';
5419
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005420 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005421 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005422 err_code |= ERR_ALERT | ERR_FATAL;
5423 args[arg] = line;
5424 }
5425
Willy Tarreau540abe42007-05-02 20:50:16 +02005426 /* zero out remaining args and ensure that at least one entry
5427 * is zeroed out.
5428 */
5429 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 args[arg] = line;
5431 }
5432
Willy Tarreau3842f002009-06-14 11:39:52 +02005433 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005434 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005435 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005436 for (arg=0; *args[arg+1]; arg++)
5437 args[arg] = args[arg+1]; // shift args after inversion
5438 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005439 else if (!strcmp(args[0], "default")) {
5440 kwm = KWM_DEF;
5441 for (arg=0; *args[arg+1]; arg++)
5442 args[arg] = args[arg+1]; // shift args after inversion
5443 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005444
Willy Tarreau3842f002009-06-14 11:39:52 +02005445 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5446 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005447 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005448 }
5449
Willy Tarreau977b8e42006-12-29 14:19:17 +01005450 if (!strcmp(args[0], "listen") ||
5451 !strcmp(args[0], "frontend") ||
5452 !strcmp(args[0], "backend") ||
5453 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005454 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005456 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005457 cursection = strdup(args[0]);
5458 }
5459 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005460 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005461 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005462 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005463 }
5464 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005465 confsect = CFG_USERLIST;
5466 free(cursection);
5467 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005468 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005469 else if (!strcmp(args[0], "peers")) {
5470 confsect = CFG_PEERS;
5471 free(cursection);
5472 cursection = strdup(args[0]);
5473 }
5474
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 /* else it's a section keyword */
5476
5477 switch (confsect) {
5478 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005479 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005480 break;
5481 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005482 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005484 case CFG_USERLIST:
5485 err_code |= cfg_parse_users(file, linenum, args, kwm);
5486 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005487 case CFG_PEERS:
5488 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5489 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005491 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005492 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005494
5495 if (err_code & ERR_ABORT)
5496 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005498 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005499 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005501 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005502}
5503
Willy Tarreaubb925012009-07-23 13:36:36 +02005504/*
5505 * Returns the error code, 0 if OK, or any combination of :
5506 * - ERR_ABORT: must abort ASAP
5507 * - ERR_FATAL: we can continue parsing but not start the service
5508 * - ERR_WARN: a warning has been emitted
5509 * - ERR_ALERT: an alert has been emitted
5510 * Only the two first ones can stop processing, the two others are just
5511 * indicators.
5512 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005513int check_config_validity()
5514{
5515 int cfgerr = 0;
5516 struct proxy *curproxy = NULL;
5517 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005518 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005519 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005520 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521
5522 /*
5523 * Now, check for the integrity of all that we have collected.
5524 */
5525
5526 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005527 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005528
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005529 /* first, we will invert the proxy list order */
5530 curproxy = NULL;
5531 while (proxy) {
5532 struct proxy *next;
5533
5534 next = proxy->next;
5535 proxy->next = curproxy;
5536 curproxy = proxy;
5537 if (!next)
5538 break;
5539 proxy = next;
5540 }
5541
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005543 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546 }
5547
5548 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005549 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005550 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005551 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005552 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005553 unsigned int next_id;
5554
5555 if (!curproxy->uuid) {
5556 /* proxy ID not set, use automatic numbering with first
5557 * spare entry starting with next_pxid.
5558 */
5559 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5560 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5561 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005562 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005563 next_pxid++;
5564
Willy Tarreau55ea7572007-06-17 19:56:27 +02005565
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005567 /* ensure we don't keep listeners uselessly bound */
5568 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 curproxy = curproxy->next;
5570 continue;
5571 }
5572
Willy Tarreauff01a212009-03-15 13:46:16 +01005573 switch (curproxy->mode) {
5574 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005575 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005576 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005577 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5578 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005579 cfgerr++;
5580 }
5581
5582 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005583 Warning("config : servers will be ignored for %s '%s'.\n",
5584 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005585 break;
5586
5587 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005588 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005589 break;
5590
5591 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005592 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005593 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005594 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5595 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005596 cfgerr++;
5597 }
5598 break;
5599 }
5600
5601 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005602 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5603 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 cfgerr++;
5605 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005606
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005607 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005608 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005609 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005610 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5611 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005612 cfgerr++;
5613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005615 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005616 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5617 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 cfgerr++;
5619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005621 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005622 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5623 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005624 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005625 }
5626 }
5627 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005628 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005629 /* If no LB algo is set in a backend, and we're not in
5630 * transparent mode, dispatch mode nor proxy mode, we
5631 * want to use balance roundrobin by default.
5632 */
5633 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5634 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 }
5636 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005637
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005638 if (curproxy->options2 & PR_O2_DISPATCH) {
5639 curproxy->options &= ~PR_O_TRANSP;
5640 curproxy->options &= ~PR_O_HTTP_PROXY;
5641 }
5642 else if (curproxy->options & PR_O_HTTP_PROXY) {
5643 curproxy->options2 &= ~PR_O2_DISPATCH;
5644 curproxy->options &= ~PR_O_TRANSP;
5645 }
5646 else if (curproxy->options & PR_O_TRANSP) {
5647 curproxy->options2 &= ~PR_O2_DISPATCH;
5648 curproxy->options &= ~PR_O_HTTP_PROXY;
5649 }
5650
Willy Tarreau82936582007-11-30 15:20:09 +01005651 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5652 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005653 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5654 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005655 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005656 }
5657
Willy Tarreauef781042010-01-27 11:53:01 +01005658 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5659 curproxy->options &= ~PR_O2_CHK_SNDST;
5660 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5661 "send-state", proxy_type_str(curproxy), curproxy->id);
5662 err_code |= ERR_WARN;
5663 }
5664
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005665 /* if a default backend was specified, let's find it */
5666 if (curproxy->defbe.name) {
5667 struct proxy *target;
5668
Alex Williams96532db2009-11-01 21:27:13 -05005669 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005670 if (!target) {
5671 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5672 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005673 cfgerr++;
5674 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005675 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5676 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005677 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005678 } else {
5679 free(curproxy->defbe.name);
5680 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005681 /* we force the backend to be present on at least all of
5682 * the frontend's processes.
5683 */
5684 target->bind_proc = curproxy->bind_proc ?
5685 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686 }
5687 }
5688
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005689 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005690 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5691 /* map jump target for ACT_SETBE in req_rep chain */
5692 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005693 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005694 struct proxy *target;
5695
Willy Tarreaua496b602006-12-17 23:15:24 +01005696 if (exp->action != ACT_SETBE)
5697 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005698
Alex Williams96532db2009-11-01 21:27:13 -05005699 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005700 if (!target) {
5701 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5702 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005703 cfgerr++;
5704 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005705 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5706 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005707 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005708 } else {
5709 free((void *)exp->replace);
5710 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005711 /* we force the backend to be present on at least all of
5712 * the frontend's processes.
5713 */
5714 target->bind_proc = curproxy->bind_proc ?
5715 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005716 }
5717 }
5718 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005719
5720 /* find the target proxy for 'use_backend' rules */
5721 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005722 struct proxy *target;
5723
Alex Williams96532db2009-11-01 21:27:13 -05005724 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005725
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005726 if (!target) {
5727 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5728 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005729 cfgerr++;
5730 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005731 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5732 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005733 cfgerr++;
5734 } else {
5735 free((void *)rule->be.name);
5736 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005737 /* we force the backend to be present on at least all of
5738 * the frontend's processes.
5739 */
5740 target->bind_proc = curproxy->bind_proc ?
5741 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005742 }
5743 }
5744
Emeric Brunb982a3d2010-01-04 15:45:53 +01005745 /* find the target table for 'stick' rules */
5746 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5747 struct proxy *target;
5748
Emeric Brun1d33b292010-01-04 15:47:17 +01005749 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5750 if (mrule->flags & STK_IS_STORE)
5751 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5752
Emeric Brunb982a3d2010-01-04 15:45:53 +01005753 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005754 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005755 else
5756 target = curproxy;
5757
5758 if (!target) {
5759 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5760 curproxy->id, mrule->table.name);
5761 cfgerr++;
5762 }
5763 else if (target->table.size == 0) {
5764 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5765 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5766 cfgerr++;
5767 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005768 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005769 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5770 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5771 cfgerr++;
5772 }
5773 else {
5774 free((void *)mrule->table.name);
5775 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005776 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005777 }
5778 }
5779
5780 /* find the target table for 'store response' rules */
5781 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5782 struct proxy *target;
5783
Emeric Brun1d33b292010-01-04 15:47:17 +01005784 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5785
Emeric Brunb982a3d2010-01-04 15:45:53 +01005786 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005787 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005788 else
5789 target = curproxy;
5790
5791 if (!target) {
5792 Alert("Proxy '%s': unable to find store table '%s'.\n",
5793 curproxy->id, mrule->table.name);
5794 cfgerr++;
5795 }
5796 else if (target->table.size == 0) {
5797 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5798 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5799 cfgerr++;
5800 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005801 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005802 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5803 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5804 cfgerr++;
5805 }
5806 else {
5807 free((void *)mrule->table.name);
5808 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005809 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005810 }
5811 }
5812
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005813 /* find the target table for 'tcp-request' layer 4 rules */
5814 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5815 struct proxy *target;
5816
Willy Tarreau56123282010-08-06 19:06:56 +02005817 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005818 continue;
5819
5820 if (trule->act_prm.trk_ctr.table.n)
5821 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5822 else
5823 target = curproxy;
5824
5825 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005826 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5827 curproxy->id, trule->act_prm.trk_ctr.table.n,
5828 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005829 cfgerr++;
5830 }
5831 else if (target->table.size == 0) {
5832 Alert("Proxy '%s': table '%s' used but not configured.\n",
5833 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5834 cfgerr++;
5835 }
5836 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005837 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005838 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5839 cfgerr++;
5840 }
5841 else {
5842 free(trule->act_prm.trk_ctr.table.n);
5843 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005844 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005845 * to pass a list of counters to track and allocate them right here using
5846 * stktable_alloc_data_type().
5847 */
5848 }
5849 }
5850
Willy Tarreaud1f96522010-08-03 19:34:32 +02005851 /* find the target table for 'tcp-request' layer 6 rules */
5852 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5853 struct proxy *target;
5854
Willy Tarreau56123282010-08-06 19:06:56 +02005855 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005856 continue;
5857
5858 if (trule->act_prm.trk_ctr.table.n)
5859 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5860 else
5861 target = curproxy;
5862
5863 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005864 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5865 curproxy->id, trule->act_prm.trk_ctr.table.n,
5866 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005867 cfgerr++;
5868 }
5869 else if (target->table.size == 0) {
5870 Alert("Proxy '%s': table '%s' used but not configured.\n",
5871 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5872 cfgerr++;
5873 }
5874 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005875 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02005876 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5877 cfgerr++;
5878 }
5879 else {
5880 free(trule->act_prm.trk_ctr.table.n);
5881 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005882 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005883 * to pass a list of counters to track and allocate them right here using
5884 * stktable_alloc_data_type().
5885 */
5886 }
5887 }
5888
Emeric Brun32da3c42010-09-23 18:39:19 +02005889 if (curproxy->table.peers.name) {
5890 struct peers *curpeers = peers;
5891
5892 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5893 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5894 free((void *)curproxy->table.peers.name);
5895 curproxy->table.peers.p = peers;
5896 break;
5897 }
5898 }
5899
5900 if (!curpeers) {
5901 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5902 curproxy->id, curproxy->table.peers.name);
5903 cfgerr++;
5904 }
5905 else if (!curpeers->peers_fe) {
5906 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5907 curproxy->id, curpeers->id);
5908 cfgerr++;
5909 }
5910 }
5911
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005912 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005913 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005914 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5915 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5916 "proxy", curproxy->id);
5917 cfgerr++;
5918 goto out_uri_auth_compat;
5919 }
5920
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005921 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005922 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005923 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005924 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005925
Willy Tarreau95fa4692010-02-01 13:05:50 +01005926 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5927 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005928
5929 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005930 uri_auth_compat_req[i++] = "realm";
5931 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5932 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005933
Willy Tarreau95fa4692010-02-01 13:05:50 +01005934 uri_auth_compat_req[i++] = "unless";
5935 uri_auth_compat_req[i++] = "{";
5936 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5937 uri_auth_compat_req[i++] = "}";
5938 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005939
Willy Tarreauff011f22011-01-06 17:51:27 +01005940 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5941 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005942 cfgerr++;
5943 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005944 }
5945
Willy Tarreauff011f22011-01-06 17:51:27 +01005946 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005947
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005948 if (curproxy->uri_auth->auth_realm) {
5949 free(curproxy->uri_auth->auth_realm);
5950 curproxy->uri_auth->auth_realm = NULL;
5951 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005952
5953 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005954 }
5955out_uri_auth_compat:
5956
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005957 cfgerr += acl_find_targets(curproxy);
5958
Willy Tarreau2738a142006-07-08 17:28:09 +02005959 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005960 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005961 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005962 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005963 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005964 " | While not properly invalid, you will certainly encounter various problems\n"
5965 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005966 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005967 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005968 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005969 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005970
Willy Tarreau1fa31262007-12-03 00:36:16 +01005971 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5972 * We must still support older configurations, so let's find out whether those
5973 * parameters have been set or must be copied from contimeouts.
5974 */
5975 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005976 if (!curproxy->timeout.tarpit ||
5977 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005978 /* tarpit timeout not set. We search in the following order:
5979 * default.tarpit, curr.connect, default.connect.
5980 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005981 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005982 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005983 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005984 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005985 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005986 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005987 }
5988 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005989 (!curproxy->timeout.queue ||
5990 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005991 /* queue timeout not set. We search in the following order:
5992 * default.queue, curr.connect, default.connect.
5993 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005994 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005995 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005996 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005997 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005998 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005999 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006000 }
6001 }
6002
Willy Tarreau07a54902010-03-29 18:33:29 +02006003 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006004 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6005 curproxy->check_req = (char *)malloc(curproxy->check_len);
6006 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006007 }
6008
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006009 /* The small pools required for the capture lists */
6010 if (curproxy->nb_req_cap)
6011 curproxy->req_cap_pool = create_pool("ptrcap",
6012 curproxy->nb_req_cap * sizeof(char *),
6013 MEM_F_SHARED);
6014 if (curproxy->nb_rsp_cap)
6015 curproxy->rsp_cap_pool = create_pool("ptrcap",
6016 curproxy->nb_rsp_cap * sizeof(char *),
6017 MEM_F_SHARED);
6018
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006019 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6020 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6021 MEM_F_SHARED);
6022
Willy Tarreau86034312006-12-29 00:10:33 +01006023 /* for backwards compatibility with "listen" instances, if
6024 * fullconn is not set but maxconn is set, then maxconn
6025 * is used.
6026 */
6027 if (!curproxy->fullconn)
6028 curproxy->fullconn = curproxy->maxconn;
6029
Willy Tarreaubaaee002006-06-26 02:48:02 +02006030 /* first, we will invert the servers list order */
6031 newsrv = NULL;
6032 while (curproxy->srv) {
6033 struct server *next;
6034
6035 next = curproxy->srv->next;
6036 curproxy->srv->next = newsrv;
6037 newsrv = curproxy->srv;
6038 if (!next)
6039 break;
6040 curproxy->srv = next;
6041 }
6042
Willy Tarreaudd701652010-05-25 23:03:02 +02006043 /* assign automatic UIDs to servers which don't have one yet */
6044 next_id = 1;
6045 newsrv = curproxy->srv;
6046 while (newsrv != NULL) {
6047 if (!newsrv->puid) {
6048 /* server ID not set, use automatic numbering with first
6049 * spare entry starting with next_svid.
6050 */
6051 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6052 newsrv->conf.id.key = newsrv->puid = next_id;
6053 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6054 }
6055 next_id++;
6056 newsrv = newsrv->next;
6057 }
6058
Willy Tarreau20697042007-11-15 23:26:18 +01006059 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006060 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006061
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006062 /* We have to initialize the server lookup mechanism depending
6063 * on what LB algorithm was choosen.
6064 */
6065
6066 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6067 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6068 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006069 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6070 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6071 init_server_map(curproxy);
6072 } else {
6073 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6074 fwrr_init_server_groups(curproxy);
6075 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006076 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006077
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006078 case BE_LB_KIND_LC:
6079 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006080 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006081 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006082
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006083 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006084 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6085 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6086 chash_init_server_tree(curproxy);
6087 } else {
6088 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6089 init_server_map(curproxy);
6090 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006091 break;
6092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093
6094 if (curproxy->options & PR_O_LOGASAP)
6095 curproxy->to_log &= ~LW_BYTES;
6096
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006097 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6098 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6099 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6100 proxy_type_str(curproxy), curproxy->id);
6101 err_code |= ERR_WARN;
6102 }
6103
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006104 if (curproxy->mode != PR_MODE_HTTP) {
6105 int optnum;
6106
6107 if (curproxy->options & PR_O_COOK_ANY) {
6108 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6109 proxy_type_str(curproxy), curproxy->id);
6110 err_code |= ERR_WARN;
6111 }
6112
6113 if (curproxy->uri_auth) {
6114 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6115 proxy_type_str(curproxy), curproxy->id);
6116 err_code |= ERR_WARN;
6117 curproxy->uri_auth = NULL;
6118 }
6119
6120 if (curproxy->options & PR_O_FWDFOR) {
6121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6122 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6123 err_code |= ERR_WARN;
6124 curproxy->options &= ~PR_O_FWDFOR;
6125 }
6126
6127 if (curproxy->options & PR_O_ORGTO) {
6128 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6129 "originalto", proxy_type_str(curproxy), curproxy->id);
6130 err_code |= ERR_WARN;
6131 curproxy->options &= ~PR_O_ORGTO;
6132 }
6133
6134 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6135 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6136 (curproxy->cap & cfg_opts[optnum].cap) &&
6137 (curproxy->options & cfg_opts[optnum].val)) {
6138 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6139 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6140 err_code |= ERR_WARN;
6141 curproxy->options &= ~cfg_opts[optnum].val;
6142 }
6143 }
6144
6145 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6146 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6147 (curproxy->cap & cfg_opts2[optnum].cap) &&
6148 (curproxy->options2 & cfg_opts2[optnum].val)) {
6149 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6150 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6151 err_code |= ERR_WARN;
6152 curproxy->options2 &= ~cfg_opts2[optnum].val;
6153 }
6154 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006155
Willy Tarreauefa5f512010-03-30 20:13:29 +02006156#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006157 if (curproxy->bind_hdr_occ) {
6158 curproxy->bind_hdr_occ = 0;
6159 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6160 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6161 err_code |= ERR_WARN;
6162 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006163#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006164 }
6165
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006167 * ensure that we're not cross-dressing a TCP server into HTTP.
6168 */
6169 newsrv = curproxy->srv;
6170 while (newsrv != NULL) {
6171 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006172 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6173 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006174 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006175 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006176
Willy Tarreauefa5f512010-03-30 20:13:29 +02006177#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006178 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6179 newsrv->bind_hdr_occ = 0;
6180 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6181 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6182 err_code |= ERR_WARN;
6183 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006184#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006185 newsrv = newsrv->next;
6186 }
6187
6188 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189 * If this server supports a maxconn parameter, it needs a dedicated
6190 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006191 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192 */
6193 newsrv = curproxy->srv;
6194 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006195 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196 /* Only 'minconn' was specified, or it was higher than or equal
6197 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6198 * this will avoid further useless expensive computations.
6199 */
6200 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006201 } else if (newsrv->maxconn && !newsrv->minconn) {
6202 /* minconn was not specified, so we set it to maxconn */
6203 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006204 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006205 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6206 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006207 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208 }
6209
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006210 if (newsrv->trackit) {
6211 struct proxy *px;
6212 struct server *srv;
6213 char *pname, *sname;
6214
6215 pname = newsrv->trackit;
6216 sname = strrchr(pname, '/');
6217
6218 if (sname)
6219 *sname++ = '\0';
6220 else {
6221 sname = pname;
6222 pname = NULL;
6223 }
6224
6225 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006226 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006227 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006228 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6229 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006230 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006231 cfgerr++;
6232 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006233 }
6234 } else
6235 px = curproxy;
6236
6237 srv = findserver(px, sname);
6238 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006239 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6240 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006241 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006242 cfgerr++;
6243 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006244 }
6245
6246 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006247 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006248 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006249 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006250 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006251 cfgerr++;
6252 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006253 }
6254
6255 if (curproxy != px &&
6256 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006257 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006258 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006259 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006260 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006261 cfgerr++;
6262 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006263 }
6264
6265 newsrv->tracked = srv;
6266 newsrv->tracknext = srv->tracknext;
6267 srv->tracknext = newsrv;
6268
6269 free(newsrv->trackit);
6270 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006271 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 newsrv = newsrv->next;
6273 }
6274
Willy Tarreauc1a21672009-08-16 22:37:44 +02006275 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006276 curproxy->accept = frontend_accept;
6277
Willy Tarreauc1a21672009-08-16 22:37:44 +02006278 if (curproxy->tcp_req.inspect_delay ||
6279 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006280 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006281
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006282 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006283 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006284 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006285 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006286
6287 /* both TCP and HTTP must check switching rules */
6288 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6289 }
6290
6291 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006292 if (curproxy->tcp_req.inspect_delay ||
6293 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6294 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6295
Emeric Brun97679e72010-09-23 17:56:44 +02006296 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6297 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6298
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006299 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006300 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006301 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006302 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006303
6304 /* If the backend does requires RDP cookie persistence, we have to
6305 * enable the corresponding analyser.
6306 */
6307 if (curproxy->options2 & PR_O2_RDPC_PRST)
6308 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6309 }
6310
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006311 listener = NULL;
6312 while (curproxy->listen) {
6313 struct listener *next;
6314
6315 next = curproxy->listen->next;
6316 curproxy->listen->next = listener;
6317 listener = curproxy->listen;
6318
6319 if (!next)
6320 break;
6321
6322 curproxy->listen = next;
6323 }
6324
Willy Tarreaue6b98942007-10-29 01:09:36 +01006325 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006326 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006327 listener = curproxy->listen;
6328 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006329 if (!listener->luid) {
6330 /* listener ID not set, use automatic numbering with first
6331 * spare entry starting with next_luid.
6332 */
6333 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6334 listener->conf.id.key = listener->luid = next_id;
6335 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006336 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006337 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006338
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006339 /* enable separate counters */
6340 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6341 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6342 if (!listener->name) {
6343 sprintf(trash, "sock-%d", listener->luid);
6344 listener->name = strdup(trash);
6345 }
6346 }
6347
Willy Tarreaue6b98942007-10-29 01:09:36 +01006348 if (curproxy->options & PR_O_TCP_NOLING)
6349 listener->options |= LI_O_NOLINGER;
6350 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006351 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006352 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006353 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006354 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006355 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006356 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006357
Willy Tarreau8a956912010-10-15 14:27:08 +02006358 if (listener->options & LI_O_ACC_PROXY)
6359 listener->analysers |= AN_REQ_DECODE_PROXY;
6360
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006361 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6362 listener->options |= LI_O_TCP_RULES;
6363
Willy Tarreaude3041d2010-05-31 10:56:17 +02006364 if (curproxy->mon_mask.s_addr)
6365 listener->options |= LI_O_CHK_MONNET;
6366
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006367 /* smart accept mode is automatic in HTTP mode */
6368 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6369 (curproxy->mode == PR_MODE_HTTP &&
6370 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6371 listener->options |= LI_O_NOQUICKACK;
6372
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006373 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006374 listener = listener->next;
6375 }
6376
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006377 /* Check multi-process mode compatibility for the current proxy */
6378 if (global.nbproc > 1) {
6379 int nbproc = 0;
6380 if (curproxy->bind_proc) {
6381 int proc;
6382 for (proc = 0; proc < global.nbproc; proc++) {
6383 if (curproxy->bind_proc & (1 << proc)) {
6384 nbproc++;
6385 }
6386 }
6387 } else {
6388 nbproc = global.nbproc;
6389 }
6390 if (curproxy->table.peers.name) {
6391 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6392 curproxy->id);
6393 cfgerr++;
6394 }
6395 if (nbproc > 1) {
6396 if (curproxy->uri_auth) {
6397 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6398 curproxy->id);
6399 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6400 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6401 curproxy->id);
6402 }
6403 }
6404 if (curproxy->appsession_name) {
6405 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6406 curproxy->id);
6407 }
6408 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6409 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6410 curproxy->id);
6411 }
6412 }
6413 }
6414
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 curproxy = curproxy->next;
6416 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006417
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006418 /* Check multi-process mode compatibility */
6419 if (global.nbproc > 1) {
6420 if (global.stats_fe) {
6421 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6422 }
6423 }
6424
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006425 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6426 struct auth_users *curuser;
6427 int g;
6428
6429 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6430 unsigned int group_mask = 0;
6431 char *group = NULL;
6432
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006433 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006434 continue;
6435
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006436 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006437
6438 for (g = 0; g < curuserlist->grpcnt; g++)
6439 if (!strcmp(curuserlist->groups[g], group))
6440 break;
6441
6442 if (g == curuserlist->grpcnt) {
6443 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6444 curuserlist->name, group, curuser->user);
6445 err_code |= ERR_ALERT | ERR_FATAL;
6446 goto out;
6447 }
6448
6449 group_mask |= (1 << g);
6450 }
6451
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006452 free(curuser->u.groups);
6453 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006454 }
6455
6456 for (g = 0; g < curuserlist->grpcnt; g++) {
6457 char *user = NULL;
6458
6459 if (!curuserlist->groupusers[g])
6460 continue;
6461
6462 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6463 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6464 if (!strcmp(curuser->user, user))
6465 break;
6466
6467 if (!curuser) {
6468 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6469 curuserlist->name, user, curuserlist->groups[g]);
6470 err_code |= ERR_ALERT | ERR_FATAL;
6471 goto out;
6472 }
6473
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006474 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006475 }
6476
6477 free(curuserlist->groupusers[g]);
6478 }
6479
6480 free(curuserlist->groupusers);
6481
6482#ifdef DEBUG_AUTH
6483 for (g = 0; g < curuserlist->grpcnt; g++) {
6484 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6485
6486 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6487 if (curuser->group_mask & (1 << g))
6488 fprintf(stderr, " %s", curuser->user);
6489 }
6490
6491 fprintf(stderr, "\n");
6492 }
6493#endif
6494
6495 }
6496
Willy Tarreau056f5682010-06-06 15:51:11 +02006497 /* initialize stick-tables on backend capable proxies. This must not
6498 * be done earlier because the data size may be discovered while parsing
6499 * other proxies.
6500 */
6501 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006502 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006503
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006504 /*
6505 * Recount currently required checks.
6506 */
6507
6508 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6509 int optnum;
6510
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006511 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6512 if (curproxy->options & cfg_opts[optnum].val)
6513 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006514
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006515 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6516 if (curproxy->options2 & cfg_opts2[optnum].val)
6517 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006518 }
6519
Willy Tarreaubb925012009-07-23 13:36:36 +02006520 if (cfgerr > 0)
6521 err_code |= ERR_ALERT | ERR_FATAL;
6522 out:
6523 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006524}
6525
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006526/*
6527 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6528 * parsing sessions.
6529 */
6530void cfg_register_keywords(struct cfg_kw_list *kwl)
6531{
6532 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6533}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006535/*
6536 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6537 */
6538void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6539{
6540 LIST_DEL(&kwl->list);
6541 LIST_INIT(&kwl->list);
6542}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543
6544/*
6545 * Local variables:
6546 * c-indent-level: 8
6547 * c-basic-offset: 8
6548 * End:
6549 */