blob: 14c513146f05ac4d407610203f59a45beba1e2b0 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020047#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020048#include <proto/lb_fwlc.h>
49#include <proto/lb_fwrr.h>
50#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010052#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020053#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010054#include <proto/protocols.h>
55#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020056#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010057#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010058#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020059#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010061#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010063#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064
65
Willy Tarreauf3c69202006-07-09 16:42:34 +020066/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
67 * ssl-hello-chk option to ensure that the remote server speaks SSL.
68 *
69 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
70 */
71const char sslv3_client_hello_pkt[] = {
72 "\x16" /* ContentType : 0x16 = Hanshake */
73 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
74 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
75 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
76 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
77 "\x03\x00" /* Hello Version : 0x0300 = v3 */
78 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
79 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
80 "\x00" /* Session ID length : empty (no session ID) */
81 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
82 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
83 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
84 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
85 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
86 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
87 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
88 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
89 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
90 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
91 "\x00\x38" "\x00\x39" "\x00\x3A"
92 "\x01" /* Compression Length : 0x01 = 1 byte for types */
93 "\x00" /* Compression Type : 0x00 = NULL compression */
94};
95
Willy Tarreau3842f002009-06-14 11:39:52 +020096/* various keyword modifiers */
97enum kw_mod {
98 KWM_STD = 0, /* normal */
99 KWM_NO, /* "no" prefixed before the keyword */
100 KWM_DEF, /* "default" prefixed before the keyword */
101};
102
Willy Tarreau13943ab2006-12-31 00:24:10 +0100103/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100104struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105 const char *name;
106 unsigned int val;
107 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100108 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100109 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100110};
111
112/* proxy->options */
113static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100115 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
116 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
117 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
118 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
119 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
120 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
121 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
123 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
125 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
127 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
128 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
129 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
130 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100131#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100133#else
134 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100135#endif
136
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100137 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138};
139
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140/* proxy->options2 */
141static const struct cfg_opt cfg_opts2[] =
142{
143#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
145 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
146 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100147#else
148 { "splice-request", 0, 0, 0, 0 },
149 { "splice-response", 0, 0, 0, 0 },
150 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
153 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
155 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
156 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
157 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
158 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
159 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
160 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
161 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200162 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100163 { NULL, 0, 0, 0 }
164};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165
Willy Tarreau6daf3432008-01-22 16:44:08 +0100166static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
168int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100169int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200171/* List head of all known configuration keywords */
172static struct cfg_kw_list cfg_keywords = {
173 .list = LIST_HEAD_INIT(cfg_keywords.list)
174};
175
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176/*
177 * converts <str> to a list of listeners which are dynamically allocated.
178 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
179 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
180 * - <port> is a numerical port from 1 to 65535 ;
181 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
182 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200183 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100185static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186{
187 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100188 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189 int port, end;
190
191 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200192
Willy Tarreaubaaee002006-06-26 02:48:02 +0200193 while (next && *next) {
194 struct sockaddr_storage ss;
195
196 str = next;
197 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100198 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 *next++ = 0;
200 }
201
Emeric Bruned760922010-10-22 17:59:25 +0200202 if (*str == '/') {
203 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
204 /* so compute max path */
205 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
206 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 +0200207
Emeric Bruned760922010-10-22 17:59:25 +0200208 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100209 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
210 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200211 goto fail;
212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200215 ss.ss_family = AF_UNIX;
216 if (global.unix_bind.prefix) {
217 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
218 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 }
Emeric Bruned760922010-10-22 17:59:25 +0200220 else {
221 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
222 }
223 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 }
225 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 ss2 = str2sa_range(str, &port, &end);
229 if (!ss2) {
230 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
231 file, line, str);
232 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200233 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100235 if (!port) {
236 Alert("parsing [%s:%d] : missing port number: '%s'\n",
237 file, line, str);
238 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100241 /* OK the address looks correct */
242 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Emeric Bruned760922010-10-22 17:59:25 +0200244 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
246 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200247 goto fail;
248 }
249
250 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100251 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
252 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200253 goto fail;
254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255 }
256
257 for (; port <= end; port++) {
258 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200259 l->next = curproxy->listen;
260 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261
262 l->fd = -1;
263 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100264 l->state = LI_INIT;
265
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100266 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100268 tcpv4_add_listener(l);
269 }
Emeric Bruned760922010-10-22 17:59:25 +0200270 else if (ss.ss_family == AF_INET6) {
271 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
272 tcpv6_add_listener(l);
273 }
274 else {
275 l->perm.ux.gid = l->perm.ux.uid = -1;
276 l->perm.ux.mode = 0;
277 uxst_add_listener(l);
278 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200279
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200280 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100281 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282 } /* end for(port) */
283 } /* end while(next) */
284 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200285 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 fail:
287 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289}
290
Willy Tarreau977b8e42006-12-29 14:19:17 +0100291/*
292 * Sends a warning if proxy <proxy> does not have at least one of the
293 * capabilities in <cap>. An optionnal <hint> may be added at the end
294 * of the warning to help the user. Returns 1 if a warning was emitted
295 * or 0 if the condition is valid.
296 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100297int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298{
299 char *msg;
300
301 switch (cap) {
302 case PR_CAP_BE: msg = "no backend"; break;
303 case PR_CAP_FE: msg = "no frontend"; break;
304 case PR_CAP_RS: msg = "no ruleset"; break;
305 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
306 default: msg = "not enough"; break;
307 }
308
309 if (!(proxy->cap & cap)) {
310 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100311 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100312 return 1;
313 }
314 return 0;
315}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316
Willy Tarreau61d18892009-03-31 10:49:21 +0200317/* Report a warning if a rule is placed after a 'block' rule.
318 * Return 1 if the warning has been emitted, otherwise 0.
319 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100320int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200321{
322 if (!LIST_ISEMPTY(&proxy->block_cond)) {
323 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
324 file, line, arg);
325 return 1;
326 }
327 return 0;
328}
329
330/* Report a warning if a rule is placed after a reqrewrite rule.
331 * Return 1 if the warning has been emitted, otherwise 0.
332 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100333int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200334{
335 if (proxy->req_exp) {
336 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
337 file, line, arg);
338 return 1;
339 }
340 return 0;
341}
342
343/* Report a warning if a rule is placed after a reqadd rule.
344 * Return 1 if the warning has been emitted, otherwise 0.
345 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100346int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200347{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100348 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200349 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
350 file, line, arg);
351 return 1;
352 }
353 return 0;
354}
355
356/* Report a warning if a rule is placed after a redirect rule.
357 * Return 1 if the warning has been emitted, otherwise 0.
358 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100359int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200360{
361 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
362 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
363 file, line, arg);
364 return 1;
365 }
366 return 0;
367}
368
369/* Report a warning if a rule is placed after a 'use_backend' rule.
370 * Return 1 if the warning has been emitted, otherwise 0.
371 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100372int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200373{
374 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
375 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
376 file, line, arg);
377 return 1;
378 }
379 return 0;
380}
381
382/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100383int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200384{
385 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
386 warnif_rule_after_reqadd(proxy, file, line, arg) ||
387 warnif_rule_after_redirect(proxy, file, line, arg) ||
388 warnif_rule_after_use_backend(proxy, file, line, arg);
389}
390
391/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100392int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200393{
394 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_redirect(proxy, file, line, arg) ||
403 warnif_rule_after_use_backend(proxy, file, line, arg);
404}
405
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100406/* Report it if a request ACL condition uses some response-only parameters. It
407 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
408 * Note that <cond> may be NULL and then will be ignored.
409 */
410static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
411{
412 struct acl *acl;
413
414 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
415 return 0;
416
417 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
418 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
419 file, line, acl ? acl->name : "(unknown)");
420 return ERR_WARN;
421}
422
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100423/* Report it if a request ACL condition uses some request-only volatile parameters.
424 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
425 * Note that <cond> may be NULL and then will be ignored.
426 */
427static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
428{
429 struct acl *acl;
430
431 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
432 return 0;
433
434 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
435 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
436 file, line, acl ? acl->name : "(unknown)");
437 return ERR_WARN;
438}
439
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100440
Willy Tarreaubaaee002006-06-26 02:48:02 +0200441/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200442 * parse a line in a <global> section. Returns the error code, 0 if OK, or
443 * any combination of :
444 * - ERR_ABORT: must abort ASAP
445 * - ERR_FATAL: we can continue parsing but not start the service
446 * - ERR_WARN: a warning has been emitted
447 * - ERR_ALERT: an alert has been emitted
448 * Only the two first ones can stop processing, the two others are just
449 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200450 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200451int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200452{
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200454
455 if (!strcmp(args[0], "global")) { /* new section */
456 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 }
459 else if (!strcmp(args[0], "daemon")) {
460 global.mode |= MODE_DAEMON;
461 }
462 else if (!strcmp(args[0], "debug")) {
463 global.mode |= MODE_DEBUG;
464 }
465 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100466 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200468 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100469 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200470 }
471 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100472 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100477 else if (!strcmp(args[0], "nosplice")) {
478 global.tune.options &= ~GTUNE_USE_SPLICE;
479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480 else if (!strcmp(args[0], "quiet")) {
481 global.mode |= MODE_QUIET;
482 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200483 else if (!strcmp(args[0], "tune.maxpollevents")) {
484 if (global.tune.maxpollevents != 0) {
485 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200486 err_code |= ERR_ALERT;
487 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200488 }
489 if (*(args[1]) == 0) {
490 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200491 err_code |= ERR_ALERT | ERR_FATAL;
492 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200493 }
494 global.tune.maxpollevents = atol(args[1]);
495 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100496 else if (!strcmp(args[0], "tune.maxaccept")) {
497 if (global.tune.maxaccept != 0) {
498 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200499 err_code |= ERR_ALERT;
500 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100501 }
502 if (*(args[1]) == 0) {
503 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200504 err_code |= ERR_ALERT | ERR_FATAL;
505 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100506 }
507 global.tune.maxaccept = atol(args[1]);
508 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200509 else if (!strcmp(args[0], "tune.chksize")) {
510 if (*(args[1]) == 0) {
511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
514 }
515 global.tune.chksize = atol(args[1]);
516 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200517 else if (!strcmp(args[0], "tune.bufsize")) {
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
522 }
523 global.tune.bufsize = atol(args[1]);
524 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
525 global.tune.maxrewrite = global.tune.bufsize / 2;
526 }
527 else if (!strcmp(args[0], "tune.maxrewrite")) {
528 if (*(args[1]) == 0) {
529 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
530 err_code |= ERR_ALERT | ERR_FATAL;
531 goto out;
532 }
533 global.tune.maxrewrite = atol(args[1]);
534 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
535 global.tune.maxrewrite = global.tune.bufsize / 2;
536 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100537 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
538 if (global.tune.client_rcvbuf != 0) {
539 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
540 err_code |= ERR_ALERT;
541 goto out;
542 }
543 if (*(args[1]) == 0) {
544 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
545 err_code |= ERR_ALERT | ERR_FATAL;
546 goto out;
547 }
548 global.tune.client_rcvbuf = atol(args[1]);
549 }
550 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
551 if (global.tune.server_rcvbuf != 0) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.tune.server_rcvbuf = atol(args[1]);
562 }
563 else if (!strcmp(args[0], "tune.sndbuf.client")) {
564 if (global.tune.client_sndbuf != 0) {
565 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
566 err_code |= ERR_ALERT;
567 goto out;
568 }
569 if (*(args[1]) == 0) {
570 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
571 err_code |= ERR_ALERT | ERR_FATAL;
572 goto out;
573 }
574 global.tune.client_sndbuf = atol(args[1]);
575 }
576 else if (!strcmp(args[0], "tune.sndbuf.server")) {
577 if (global.tune.server_sndbuf != 0) {
578 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
579 err_code |= ERR_ALERT;
580 goto out;
581 }
582 if (*(args[1]) == 0) {
583 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587 global.tune.server_sndbuf = atol(args[1]);
588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 else if (!strcmp(args[0], "uid")) {
590 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200591 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200592 err_code |= ERR_ALERT;
593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 }
600 global.uid = atol(args[1]);
601 }
602 else if (!strcmp(args[0], "gid")) {
603 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200604 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200605 err_code |= ERR_ALERT;
606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 }
608 if (*(args[1]) == 0) {
609 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200610 err_code |= ERR_ALERT | ERR_FATAL;
611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 }
613 global.gid = atol(args[1]);
614 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200615 /* user/group name handling */
616 else if (!strcmp(args[0], "user")) {
617 struct passwd *ha_user;
618 if (global.uid != 0) {
619 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 err_code |= ERR_ALERT;
621 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200622 }
623 errno = 0;
624 ha_user = getpwnam(args[1]);
625 if (ha_user != NULL) {
626 global.uid = (int)ha_user->pw_uid;
627 }
628 else {
629 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 +0200630 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200631 }
632 }
633 else if (!strcmp(args[0], "group")) {
634 struct group *ha_group;
635 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200636 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200637 err_code |= ERR_ALERT;
638 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200639 }
640 errno = 0;
641 ha_group = getgrnam(args[1]);
642 if (ha_group != NULL) {
643 global.gid = (int)ha_group->gr_gid;
644 }
645 else {
646 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 +0200647 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200648 }
649 }
650 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 else if (!strcmp(args[0], "nbproc")) {
652 if (global.nbproc != 0) {
653 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200654 err_code |= ERR_ALERT;
655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
662 global.nbproc = atol(args[1]);
663 }
664 else if (!strcmp(args[0], "maxconn")) {
665 if (global.maxconn != 0) {
666 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200667 err_code |= ERR_ALERT;
668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200669 }
670 if (*(args[1]) == 0) {
671 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200674 }
675 global.maxconn = atol(args[1]);
676#ifdef SYSTEM_MAXCONN
677 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
678 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);
679 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681 }
682#endif /* SYSTEM_MAXCONN */
683 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100684 else if (!strcmp(args[0], "maxpipes")) {
685 if (global.maxpipes != 0) {
686 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200687 err_code |= ERR_ALERT;
688 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100689 }
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100694 }
695 global.maxpipes = atol(args[1]);
696 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200697 else if (!strcmp(args[0], "ulimit-n")) {
698 if (global.rlimit_nofile != 0) {
699 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200700 err_code |= ERR_ALERT;
701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200702 }
703 if (*(args[1]) == 0) {
704 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200705 err_code |= ERR_ALERT | ERR_FATAL;
706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 }
708 global.rlimit_nofile = atol(args[1]);
709 }
710 else if (!strcmp(args[0], "chroot")) {
711 if (global.chroot != NULL) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT;
714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715 }
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 }
721 global.chroot = strdup(args[1]);
722 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200723 else if (!strcmp(args[0], "description")) {
724 int i, len=0;
725 char *d;
726
727 if (!*args[1]) {
728 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
729 file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733
734 for(i=1; *args[i]; i++)
735 len += strlen(args[i])+1;
736
737 if (global.desc)
738 free(global.desc);
739
740 global.desc = d = (char *)calloc(1, len);
741
742 d += sprintf(d, "%s", args[1]);
743 for(i=2; *args[i]; i++)
744 d += sprintf(d, " %s", args[i]);
745 }
746 else if (!strcmp(args[0], "node")) {
747 int i;
748 char c;
749
750 for (i=0; args[1][i]; i++) {
751 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100752 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
753 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200754 break;
755 }
756
757 if (!i || args[1][i]) {
758 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
759 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
760 file, linenum, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764
765 if (global.node)
766 free(global.node);
767
768 global.node = strdup(args[1]);
769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200770 else if (!strcmp(args[0], "pidfile")) {
771 if (global.pidfile != NULL) {
772 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
781 global.pidfile = strdup(args[1]);
782 }
Emeric Bruned760922010-10-22 17:59:25 +0200783 else if (!strcmp(args[0], "unix-bind")) {
784 int cur_arg = 1;
785 while (*(args[cur_arg])) {
786 if (!strcmp(args[cur_arg], "prefix")) {
787 if (global.unix_bind.prefix != NULL) {
788 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
789 err_code |= ERR_ALERT;
790 cur_arg += 2;
791 continue;
792 }
793
794 if (*(args[cur_arg+1]) == 0) {
795 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.unix_bind.prefix = strdup(args[cur_arg+1]);
800 cur_arg += 2;
801 continue;
802 }
803
804 if (!strcmp(args[cur_arg], "mode")) {
805
806 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
807 cur_arg += 2;
808 continue;
809 }
810
811 if (!strcmp(args[cur_arg], "uid")) {
812
813 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
814 cur_arg += 2;
815 continue;
816 }
817
818 if (!strcmp(args[cur_arg], "gid")) {
819
820 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
821 cur_arg += 2;
822 continue;
823 }
824
825 if (!strcmp(args[cur_arg], "user")) {
826 struct passwd *user;
827
828 user = getpwnam(args[cur_arg + 1]);
829 if (!user) {
830 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
831 file, linenum, args[0], args[cur_arg + 1 ]);
832 err_code |= ERR_ALERT | ERR_FATAL;
833 goto out;
834 }
835
836 global.unix_bind.ux.uid = user->pw_uid;
837 cur_arg += 2;
838 continue;
839 }
840
841 if (!strcmp(args[cur_arg], "group")) {
842 struct group *group;
843
844 group = getgrnam(args[cur_arg + 1]);
845 if (!group) {
846 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
847 file, linenum, args[0], args[cur_arg + 1 ]);
848 err_code |= ERR_ALERT | ERR_FATAL;
849 goto out;
850 }
851
852 global.unix_bind.ux.gid = group->gr_gid;
853 cur_arg += 2;
854 continue;
855 }
856
857 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
858 file, linenum, args[0]);
859 err_code |= ERR_ALERT | ERR_FATAL;
860 goto out;
861 }
862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100864 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200865 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866
867 if (*(args[1]) == 0 || *(args[2]) == 0) {
868 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871 }
872
873 facility = get_log_facility(args[2]);
874 if (facility < 0) {
875 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200876 err_code |= ERR_ALERT | ERR_FATAL;
877 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 }
879
880 level = 7; /* max syslog level = debug */
881 if (*(args[3])) {
882 level = get_log_level(args[3]);
883 if (level < 0) {
884 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT | ERR_FATAL;
886 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 }
889
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200890 minlvl = 0; /* limit syslog level to this level (emerg) */
891 if (*(args[4])) {
892 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200893 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200894 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT | ERR_FATAL;
896 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200897 }
898 }
899
Robert Tsai81ae1952007-12-05 10:47:29 +0100900 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100901 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100902 if (!sk) {
903 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100904 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100908 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100909 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100910 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100911 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100912 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
David du Colombier11bcb6c2011-03-24 12:23:00 +0100916 logsrv.addr = *sk;
917 if (!get_host_port(&logsrv.addr))
918 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920
921 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100922 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 global.logfac1 = facility;
924 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200925 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100928 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929 global.logfac2 = facility;
930 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200931 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 else {
934 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200935 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200937 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100938 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
939 char *name;
940 int len;
941
942 if (global.log_send_hostname != NULL) {
943 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
944 err_code |= ERR_ALERT;
945 goto out;
946 }
947
948 if (*(args[1]))
949 name = args[1];
950 else
951 name = hostname;
952
953 len = strlen(name);
954
955 /* We'll add a space after the name to respect the log format */
956 free(global.log_send_hostname);
957 global.log_send_hostname = malloc(len + 2);
958 snprintf(global.log_send_hostname, len + 2, "%s ", name);
959 }
Kevinm48936af2010-12-22 16:08:21 +0000960 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
961 if (*(args[1]) == 0) {
962 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
963 err_code |= ERR_ALERT | ERR_FATAL;
964 goto out;
965 }
966 free(global.log_tag);
967 global.log_tag = strdup(args[1]);
968 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200969 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
970 if (global.spread_checks != 0) {
971 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200972 err_code |= ERR_ALERT;
973 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200974 }
975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200979 }
980 global.spread_checks = atol(args[1]);
981 if (global.spread_checks < 0 || global.spread_checks > 50) {
982 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200983 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 }
986 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200987 struct cfg_kw_list *kwl;
988 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200989 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200990
991 list_for_each_entry(kwl, &cfg_keywords.list, list) {
992 for (index = 0; kwl->kw[index].kw != NULL; index++) {
993 if (kwl->kw[index].section != CFG_GLOBAL)
994 continue;
995 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
996 /* prepare error message just in case */
997 snprintf(trash, sizeof(trash),
998 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200999 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1000 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001001 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001002 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001003 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001004 else if (rc > 0) {
1005 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001006 err_code |= ERR_WARN;
1007 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001008 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001009 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001010 }
1011 }
1012 }
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001016 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001017
Willy Tarreau058e9072009-07-20 09:30:05 +02001018 out:
1019 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020}
1021
Willy Tarreau97cb7802010-01-03 20:23:58 +01001022/* Perform the most basic initialization of a proxy :
1023 * memset(), list_init(*), reset_timeouts(*).
1024 */
1025static void init_new_proxy(struct proxy *p)
1026{
1027 memset(p, 0, sizeof(struct proxy));
1028 LIST_INIT(&p->pendconns);
1029 LIST_INIT(&p->acl);
Willy Tarreauff011f22011-01-06 17:51:27 +01001030 LIST_INIT(&p->http_req_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001031 LIST_INIT(&p->block_cond);
1032 LIST_INIT(&p->redirect_rules);
1033 LIST_INIT(&p->mon_fail_cond);
1034 LIST_INIT(&p->switching_rules);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02001035 LIST_INIT(&p->persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +01001036 LIST_INIT(&p->sticking_rules);
1037 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001038 LIST_INIT(&p->tcp_req.inspect_rules);
Emeric Brun97679e72010-09-23 17:56:44 +02001039 LIST_INIT(&p->tcp_rep.inspect_rules);
Willy Tarreauab786192010-05-23 22:39:25 +02001040 LIST_INIT(&p->tcp_req.l4_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01001041 LIST_INIT(&p->req_add);
1042 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +01001043
1044 /* Timeouts are defined as -1 */
1045 proxy_reset_timeouts(p);
Emeric Brun97679e72010-09-23 17:56:44 +02001046 p->tcp_rep.inspect_delay = TICK_ETERNITY;
Willy Tarreau97cb7802010-01-03 20:23:58 +01001047}
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001049void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001051 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 defproxy.mode = PR_MODE_TCP;
1053 defproxy.state = PR_STNEW;
1054 defproxy.maxconn = cfg_maxpconn;
1055 defproxy.conn_retries = CONN_RETRIES;
1056 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001057
1058 defproxy.defsrv.inter = DEF_CHKINTR;
1059 defproxy.defsrv.fastinter = 0;
1060 defproxy.defsrv.downinter = 0;
1061 defproxy.defsrv.rise = DEF_RISETIME;
1062 defproxy.defsrv.fall = DEF_FALLTIME;
1063 defproxy.defsrv.check_port = 0;
1064 defproxy.defsrv.maxqueue = 0;
1065 defproxy.defsrv.minconn = 0;
1066 defproxy.defsrv.maxconn = 0;
1067 defproxy.defsrv.slowstart = 0;
1068 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1069 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1070 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001071}
1072
Willy Tarreauade5ec42010-01-28 19:33:49 +01001073
1074static int create_cond_regex_rule(const char *file, int line,
1075 struct proxy *px, int dir, int action, int flags,
1076 const char *cmd, const char *reg, const char *repl,
1077 const char **cond_start)
1078{
1079 regex_t *preg = NULL;
1080 const char *err;
1081 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001082 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001083
1084 if (px == &defproxy) {
1085 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto err;
1088 }
1089
1090 if (*reg == 0) {
1091 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto err;
1094 }
1095
1096 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1097 err_code |= ERR_WARN;
1098
Willy Tarreau5321c422010-01-28 20:35:13 +01001099 if (cond_start &&
1100 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1101 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1102 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1103 file, line, cmd);
1104 err_code |= ERR_ALERT | ERR_FATAL;
1105 goto err;
1106 }
1107 }
1108 else if (cond_start && **cond_start) {
1109 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1110 file, line, cmd, *cond_start);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto err;
1113 }
1114
1115 if (dir == ACL_DIR_REQ)
1116 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001117 else
1118 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001119
Willy Tarreauade5ec42010-01-28 19:33:49 +01001120 preg = calloc(1, sizeof(regex_t));
1121 if (!preg) {
1122 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1123 err_code = ERR_ALERT | ERR_FATAL;
1124 goto err;
1125 }
1126
1127 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1128 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1129 err_code = ERR_ALERT | ERR_FATAL;
1130 goto err;
1131 }
1132
1133 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001134 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001135 if (repl && err) {
1136 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1137 file, line, cmd, *err);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto err;
1140 }
1141
1142 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1143 err_code |= ERR_WARN;
1144
1145 return err_code;
1146 err:
1147 free(preg);
1148 return err_code;
1149}
1150
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001152 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001153 * Returns the error code, 0 if OK, or any combination of :
1154 * - ERR_ABORT: must abort ASAP
1155 * - ERR_FATAL: we can continue parsing but not start the service
1156 * - ERR_WARN: a warning has been emitted
1157 * - ERR_ALERT: an alert has been emitted
1158 * Only the two first ones can stop processing, the two others are just
1159 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001161int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1162{
1163 static struct peers *curpeers = NULL;
1164 struct peer *newpeer = NULL;
1165 const char *err;
1166 int err_code = 0;
1167
1168 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1169
1170 err = invalid_char(args[1]);
1171 if (err) {
1172 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1173 file, linenum, *err, args[0], args[1]);
1174 err_code |= ERR_ALERT | ERR_FATAL;
1175 }
1176
1177 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1178 /*
1179 * If there are two proxies with the same name only following
1180 * combinations are allowed:
1181 */
1182 if (strcmp(curpeers->id, args[1]) == 0) {
1183 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1184 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1185 err_code |= ERR_WARN;
1186 }
1187 }
1188
1189 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1190 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1191 err_code |= ERR_ALERT | ERR_ABORT;
1192 goto out;
1193 }
1194
1195 curpeers->next = peers;
1196 peers = curpeers;
1197 curpeers->conf.file = file;
1198 curpeers->conf.line = linenum;
1199 curpeers->last_change = now.tv_sec;
1200 curpeers->id = strdup(args[1]);
1201 }
1202 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1203 char *rport, *raddr;
1204 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001205 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001206
1207 if (!*args[2]) {
1208 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1209 file, linenum, args[0]);
1210 err_code |= ERR_ALERT | ERR_FATAL;
1211 goto out;
1212 }
1213
1214 err = invalid_char(args[1]);
1215 if (err) {
1216 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1217 file, linenum, *err, args[1]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221
1222 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1224 err_code |= ERR_ALERT | ERR_ABORT;
1225 goto out;
1226 }
1227
1228 /* the peers are linked backwards first */
1229 curpeers->count++;
1230 newpeer->next = curpeers->remote;
1231 curpeers->remote = newpeer;
1232 newpeer->peers = curpeers;
1233 newpeer->conf.file = file;
1234 newpeer->conf.line = linenum;
1235
1236 newpeer->last_change = now.tv_sec;
1237 newpeer->id = strdup(args[1]);
1238
1239 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001240 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001241 if (rport) {
1242 *rport++ = 0;
1243 realport = atol(rport);
1244 }
1245 if (!realport) {
1246 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250
Willy Tarreaufab5a432011-03-04 15:31:53 +01001251 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001252 free(raddr);
1253 if (!sk) {
1254 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258 newpeer->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001259
1260 switch (newpeer->addr.ss_family) {
1261 case AF_INET:
1262 ((struct sockaddr_in *)&newpeer->addr)->sin_port = htons(realport);
1263 break;
1264 case AF_INET6:
1265 ((struct sockaddr_in6 *)&newpeer->addr)->sin6_port = htons(realport);
1266 break;
1267 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001268
1269 if (strcmp(newpeer->id, localpeer) == 0) {
1270 /* Current is local peer, it define a frontend */
1271 newpeer->local = 1;
1272
1273 if (!curpeers->peers_fe) {
1274 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1276 err_code |= ERR_ALERT | ERR_ABORT;
1277 goto out;
1278 }
1279 curpeers->peers_fe->parent = curpeers;
1280
1281 LIST_INIT(&(curpeers->peers_fe)->pendconns);
1282 LIST_INIT(&(curpeers->peers_fe)->acl);
1283 LIST_INIT(&(curpeers->peers_fe)->block_cond);
1284 LIST_INIT(&(curpeers->peers_fe)->redirect_rules);
1285 LIST_INIT(&(curpeers->peers_fe)->mon_fail_cond);
1286 LIST_INIT(&(curpeers->peers_fe)->switching_rules);
1287 LIST_INIT(&(curpeers->peers_fe)->tcp_req.inspect_rules);
1288 LIST_INIT(&(curpeers->peers_fe)->tcp_rep.inspect_rules);
1289
1290 proxy_reset_timeouts(curpeers->peers_fe);
1291
1292 curpeers->peers_fe->last_change = now.tv_sec;
1293 curpeers->peers_fe->id = strdup(args[1]);
1294 curpeers->peers_fe->cap = PR_CAP_FE;
1295 curpeers->peers_fe->maxconn = 65000;
1296 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1297 curpeers->peers_fe->timeout.connect = 5000;
1298 curpeers->peers_fe->accept = peer_accept;
1299 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001300 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001301 err_code |= ERR_FATAL;
1302 goto out;
1303 }
1304 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1305 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1306 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1307 curpeers->peers_fe->listen->accept = session_accept;
1308 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1309 curpeers->peers_fe->listen->handler = process_session;
1310 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1311 }
1312 }
1313 } /* neither "peer" nor "peers" */
1314 else if (*args[0] != 0) {
1315 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1316 err_code |= ERR_ALERT | ERR_FATAL;
1317 goto out;
1318 }
1319
1320out:
1321 return err_code;
1322}
1323
1324
Willy Tarreau3842f002009-06-14 11:39:52 +02001325int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326{
1327 static struct proxy *curproxy = NULL;
1328 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001329 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001330 int rc;
1331 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001332 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001333 struct acl_cond *cond = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001334
Willy Tarreau977b8e42006-12-29 14:19:17 +01001335 if (!strcmp(args[0], "listen"))
1336 rc = PR_CAP_LISTEN;
1337 else if (!strcmp(args[0], "frontend"))
1338 rc = PR_CAP_FE | PR_CAP_RS;
1339 else if (!strcmp(args[0], "backend"))
1340 rc = PR_CAP_BE | PR_CAP_RS;
1341 else if (!strcmp(args[0], "ruleset"))
1342 rc = PR_CAP_RS;
1343 else
1344 rc = PR_CAP_NONE;
1345
1346 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001347 if (!*args[1]) {
1348 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1349 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1350 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001351 err_code |= ERR_ALERT | ERR_ABORT;
1352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001354
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001355 err = invalid_char(args[1]);
1356 if (err) {
1357 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1358 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001359 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001360 }
1361
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001362 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1363 /*
1364 * If there are two proxies with the same name only following
1365 * combinations are allowed:
1366 *
1367 * listen backend frontend ruleset
1368 * listen - - - -
1369 * backend - - OK -
1370 * frontend - OK - -
1371 * ruleset - - - -
1372 */
1373
1374 if (!strcmp(curproxy->id, args[1]) &&
1375 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1376 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001377 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1378 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1379 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001380 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001381 }
1382 }
1383
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1385 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001386 err_code |= ERR_ALERT | ERR_ABORT;
1387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001389
Willy Tarreau97cb7802010-01-03 20:23:58 +01001390 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 curproxy->next = proxy;
1392 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001393 curproxy->conf.file = file;
1394 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001395 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001396 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001397 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398
1399 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001400 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001401 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001402 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001403 err_code |= ERR_FATAL;
1404 goto out;
1405 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001406 new = curproxy->listen;
1407 while (new != last) {
1408 new->conf.file = file;
1409 new->conf.line = linenum;
1410 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001411 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413 }
1414
1415 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001416 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001417 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001418
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001421 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001422 curproxy->no_options = defproxy.no_options;
1423 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001424 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001425 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001426 curproxy->except_net = defproxy.except_net;
1427 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001428 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001429 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001431 if (defproxy.fwdfor_hdr_len) {
1432 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1433 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1434 }
1435
Willy Tarreaub86db342009-11-30 11:50:16 +01001436 if (defproxy.orgto_hdr_len) {
1437 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1438 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1439 }
1440
Willy Tarreau977b8e42006-12-29 14:19:17 +01001441 if (curproxy->cap & PR_CAP_FE) {
1442 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001443 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001444 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001445
1446 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001447 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1448 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001449
1450 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452
Willy Tarreau977b8e42006-12-29 14:19:17 +01001453 if (curproxy->cap & PR_CAP_BE) {
1454 curproxy->fullconn = defproxy.fullconn;
1455 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001457 if (defproxy.check_req) {
1458 curproxy->check_req = calloc(1, defproxy.check_len);
1459 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1460 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001461 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462
Willy Tarreau977b8e42006-12-29 14:19:17 +01001463 if (defproxy.cookie_name)
1464 curproxy->cookie_name = strdup(defproxy.cookie_name);
1465 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001466 if (defproxy.cookie_domain)
1467 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001468
Willy Tarreau31936852010-10-06 16:59:56 +02001469 if (defproxy.cookie_maxidle)
1470 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1471
1472 if (defproxy.cookie_maxlife)
1473 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1474
Emeric Brun647caf12009-06-30 17:57:00 +02001475 if (defproxy.rdp_cookie_name)
1476 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1477 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1478
Willy Tarreau01732802007-11-01 22:48:15 +01001479 if (defproxy.url_param_name)
1480 curproxy->url_param_name = strdup(defproxy.url_param_name);
1481 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001482
Benoitaffb4812009-03-25 13:02:10 +01001483 if (defproxy.hh_name)
1484 curproxy->hh_name = strdup(defproxy.hh_name);
1485 curproxy->hh_len = defproxy.hh_len;
1486 curproxy->hh_match_domain = defproxy.hh_match_domain;
1487
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001488 if (defproxy.iface_name)
1489 curproxy->iface_name = strdup(defproxy.iface_name);
1490 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001493 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 if (defproxy.capture_name)
1495 curproxy->capture_name = strdup(defproxy.capture_name);
1496 curproxy->capture_namelen = defproxy.capture_namelen;
1497 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001499
Willy Tarreau977b8e42006-12-29 14:19:17 +01001500 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001501 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001502 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001503 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001504 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001505 curproxy->uri_auth = defproxy.uri_auth;
1506 curproxy->mon_net = defproxy.mon_net;
1507 curproxy->mon_mask = defproxy.mon_mask;
1508 if (defproxy.monitor_uri)
1509 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1510 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001511 if (defproxy.defbe.name)
1512 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001513 }
1514
1515 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001516 curproxy->timeout.connect = defproxy.timeout.connect;
1517 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001518 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001519 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001520 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001521 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001522 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001523 curproxy->source_addr = defproxy.source_addr;
1524 }
1525
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 curproxy->mode = defproxy.mode;
1527 curproxy->logfac1 = defproxy.logfac1;
1528 curproxy->logsrv1 = defproxy.logsrv1;
1529 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001530 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531 curproxy->logfac2 = defproxy.logfac2;
1532 curproxy->logsrv2 = defproxy.logsrv2;
1533 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001534 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001536 curproxy->conf.used_listener_id = EB_ROOT;
1537 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001538
Willy Tarreau93893792009-07-23 13:19:11 +02001539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 }
1541 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1542 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001543 /* FIXME-20070101: we should do this too at the end of the
1544 * config parsing to free all default values.
1545 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001546 free(defproxy.check_req);
1547 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001548 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001549 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001550 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001551 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001552 free(defproxy.capture_name);
1553 free(defproxy.monitor_uri);
1554 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001555 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001556 free(defproxy.fwdfor_hdr_name);
1557 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001558 free(defproxy.orgto_hdr_name);
1559 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001560
Willy Tarreaua534fea2008-08-03 12:19:50 +02001561 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001562 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001563
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 /* we cannot free uri_auth because it might already be used */
1565 init_default_instance();
1566 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001567 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 }
1570 else if (curproxy == NULL) {
1571 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001572 err_code |= ERR_ALERT | ERR_FATAL;
1573 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 }
1575
Willy Tarreau977b8e42006-12-29 14:19:17 +01001576
1577 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001579 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001580 int cur_arg;
1581
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 if (curproxy == &defproxy) {
1583 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001587 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001588 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589
Emeric Bruned760922010-10-22 17:59:25 +02001590 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001591 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001593 err_code |= ERR_ALERT | ERR_FATAL;
1594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001596
1597 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001598
1599 /* NOTE: the following line might create several listeners if there
1600 * are comma-separated IPs or port ranges. So all further processing
1601 * will have to be applied to all listeners created after last_listen.
1602 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001603 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001604 err_code |= ERR_ALERT | ERR_FATAL;
1605 goto out;
1606 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001607
Willy Tarreau90a570f2009-10-04 20:54:54 +02001608 new_listen = curproxy->listen;
1609 while (new_listen != last_listen) {
1610 new_listen->conf.file = file;
1611 new_listen->conf.line = linenum;
1612 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001613 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001614 }
1615
Emeric Bruned760922010-10-22 17:59:25 +02001616 /* Set default global rights and owner for unix bind */
1617 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1618 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1619 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001620 cur_arg = 2;
1621 while (*(args[cur_arg])) {
1622 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1623#ifdef SO_BINDTODEVICE
1624 struct listener *l;
1625
Emeric Bruned760922010-10-22 17:59:25 +02001626 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1627 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1628 file, linenum, args[0], args[cur_arg]);
1629 err_code |= ERR_ALERT | ERR_FATAL;
1630 goto out;
1631 }
1632
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001633 if (!*args[cur_arg + 1]) {
1634 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1635 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001636 err_code |= ERR_ALERT | ERR_FATAL;
1637 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001638 }
1639
1640 for (l = curproxy->listen; l != last_listen; l = l->next)
1641 l->interface = strdup(args[cur_arg + 1]);
1642
1643 global.last_checks |= LSTCHK_NETADM;
1644
1645 cur_arg += 2;
1646 continue;
1647#else
1648 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1649 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001650 err_code |= ERR_ALERT | ERR_FATAL;
1651 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001652#endif
1653 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001654 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1655#ifdef TCP_MAXSEG
1656 struct listener *l;
1657 int mss;
1658
Emeric Bruned760922010-10-22 17:59:25 +02001659 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1660 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1661 file, linenum, args[0], args[cur_arg]);
1662 err_code |= ERR_ALERT | ERR_FATAL;
1663 goto out;
1664 }
1665
Willy Tarreaube1b9182009-06-14 18:48:19 +02001666 if (!*args[cur_arg + 1]) {
1667 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1668 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001669 err_code |= ERR_ALERT | ERR_FATAL;
1670 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001671 }
1672
Willy Tarreau48a7e722010-12-24 15:26:39 +01001673 mss = atoi(args[cur_arg + 1]);
1674 if (!mss || abs(mss) > 65535) {
1675 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001676 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001677 err_code |= ERR_ALERT | ERR_FATAL;
1678 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001679 }
1680
1681 for (l = curproxy->listen; l != last_listen; l = l->next)
1682 l->maxseg = mss;
1683
1684 cur_arg += 2;
1685 continue;
1686#else
1687 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1688 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001691#endif
1692 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001693
1694 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1695#ifdef TCP_DEFER_ACCEPT
1696 struct listener *l;
1697
1698 for (l = curproxy->listen; l != last_listen; l = l->next)
1699 l->options |= LI_O_DEF_ACCEPT;
1700
1701 cur_arg ++;
1702 continue;
1703#else
1704 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1705 file, linenum, args[0], args[cur_arg]);
1706 err_code |= ERR_ALERT | ERR_FATAL;
1707 goto out;
1708#endif
1709 }
1710
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001711 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001712#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001713 struct listener *l;
1714
Emeric Bruned760922010-10-22 17:59:25 +02001715 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1716 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1717 file, linenum, args[0], args[cur_arg]);
1718 err_code |= ERR_ALERT | ERR_FATAL;
1719 goto out;
1720 }
1721
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001722 for (l = curproxy->listen; l != last_listen; l = l->next)
1723 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001724
1725 cur_arg ++;
1726 continue;
1727#else
1728 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1729 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001732#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001733 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001734
Willy Tarreau8a956912010-10-15 14:27:08 +02001735 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1736 struct listener *l;
1737
1738 for (l = curproxy->listen; l != last_listen; l = l->next)
1739 l->options |= LI_O_ACC_PROXY;
1740
1741 cur_arg ++;
1742 continue;
1743 }
1744
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001745 if (!strcmp(args[cur_arg], "name")) {
1746 struct listener *l;
1747
1748 for (l = curproxy->listen; l != last_listen; l = l->next)
1749 l->name = strdup(args[cur_arg + 1]);
1750
1751 cur_arg += 2;
1752 continue;
1753 }
1754
1755 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001756 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001757 struct listener *l;
1758
1759 if (curproxy->listen->next != last_listen) {
1760 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1761 file, linenum, args[cur_arg]);
1762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
1764 }
1765
1766 if (!*args[cur_arg + 1]) {
1767 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1768 file, linenum, args[cur_arg]);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772
1773 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001774 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001775
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001776 if (curproxy->listen->luid <= 0) {
1777 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001778 file, linenum);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001783 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1784 if (node) {
1785 l = container_of(node, struct listener, conf.id);
1786 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1787 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1792
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001793 cur_arg += 2;
1794 continue;
1795 }
1796
Emeric Bruned760922010-10-22 17:59:25 +02001797 if (!strcmp(args[cur_arg], "mode")) {
1798
1799 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1800 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1801 file, linenum, args[0], args[cur_arg]);
1802 err_code |= ERR_ALERT | ERR_FATAL;
1803 goto out;
1804 }
1805
1806 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1807
1808 cur_arg += 2;
1809 continue;
1810 }
1811
1812 if (!strcmp(args[cur_arg], "uid")) {
1813
1814 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1815 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1816 file, linenum, args[0], args[cur_arg]);
1817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
1819 }
1820
1821 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1822 cur_arg += 2;
1823 continue;
1824 }
1825
1826 if (!strcmp(args[cur_arg], "gid")) {
1827
1828 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1829 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1830 file, linenum, args[0], args[cur_arg]);
1831 err_code |= ERR_ALERT | ERR_FATAL;
1832 goto out;
1833 }
1834
1835 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1836 cur_arg += 2;
1837 continue;
1838 }
1839
1840 if (!strcmp(args[cur_arg], "user")) {
1841 struct passwd *user;
1842
1843 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1844 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1845 file, linenum, args[0], args[cur_arg]);
1846 err_code |= ERR_ALERT | ERR_FATAL;
1847 goto out;
1848 }
1849 user = getpwnam(args[cur_arg + 1]);
1850 if (!user) {
1851 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1852 file, linenum, args[0], args[cur_arg + 1 ]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
1857 curproxy->listen->perm.ux.uid = user->pw_uid;
1858 cur_arg += 2;
1859 continue;
1860 }
1861
1862 if (!strcmp(args[cur_arg], "group")) {
1863 struct group *group;
1864
1865 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1866 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1867 file, linenum, args[0], args[cur_arg]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870 }
1871 group = getgrnam(args[cur_arg + 1]);
1872 if (!group) {
1873 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1874 file, linenum, args[0], args[cur_arg + 1 ]);
1875 err_code |= ERR_ALERT | ERR_FATAL;
1876 goto out;
1877 }
1878
1879 curproxy->listen->perm.ux.gid = group->gr_gid;
1880 cur_arg += 2;
1881 continue;
1882 }
1883
Willy Tarreau8a956912010-10-15 14:27:08 +02001884 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 +01001885 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001888 }
Willy Tarreau93893792009-07-23 13:19:11 +02001889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001890 }
1891 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1892 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1893 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001895 err_code |= ERR_ALERT | ERR_FATAL;
1896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001898 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 /* flush useless bits */
1902 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001903 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001905 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001906 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001907 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001908
Willy Tarreau1c47f852006-07-09 08:22:27 +02001909 if (!*args[1]) {
1910 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1911 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001912 err_code |= ERR_ALERT | ERR_FATAL;
1913 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001914 }
1915
Willy Tarreaua534fea2008-08-03 12:19:50 +02001916 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001917 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001918 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001919 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001920 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1921
Willy Tarreau93893792009-07-23 13:19:11 +02001922 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1925 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1926 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1927 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1928 else {
1929 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001930 err_code |= ERR_ALERT | ERR_FATAL;
1931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001932 }
1933 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001934 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001935 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001936
1937 if (curproxy == &defproxy) {
1938 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001940 err_code |= ERR_ALERT | ERR_FATAL;
1941 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001942 }
1943
1944 if (!*args[1]) {
1945 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001949 }
1950
1951 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001952 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001953
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001954 if (curproxy->uuid <= 0) {
1955 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001956 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001957 err_code |= ERR_ALERT | ERR_FATAL;
1958 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001959 }
1960
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001961 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1962 if (node) {
1963 struct proxy *target = container_of(node, struct proxy, conf.id);
1964 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1965 file, linenum, proxy_type_str(curproxy), curproxy->id,
1966 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1967 err_code |= ERR_ALERT | ERR_FATAL;
1968 goto out;
1969 }
1970 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001971 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001972 else if (!strcmp(args[0], "description")) {
1973 int i, len=0;
1974 char *d;
1975
Cyril Bonté99ed3272010-01-24 23:29:44 +01001976 if (curproxy == &defproxy) {
1977 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1978 file, linenum, args[0]);
1979 err_code |= ERR_ALERT | ERR_FATAL;
1980 goto out;
1981 }
1982
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001983 if (!*args[1]) {
1984 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1985 file, linenum, args[0]);
1986 return -1;
1987 }
1988
1989 for(i=1; *args[i]; i++)
1990 len += strlen(args[i])+1;
1991
1992 d = (char *)calloc(1, len);
1993 curproxy->desc = d;
1994
1995 d += sprintf(d, "%s", args[1]);
1996 for(i=2; *args[i]; i++)
1997 d += sprintf(d, " %s", args[i]);
1998
1999 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002000 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2001 curproxy->state = PR_STSTOPPED;
2002 }
2003 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2004 curproxy->state = PR_STNEW;
2005 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002006 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2007 int cur_arg = 1;
2008 unsigned int set = 0;
2009
2010 while (*args[cur_arg]) {
2011 int u;
2012 if (strcmp(args[cur_arg], "all") == 0) {
2013 set = 0;
2014 break;
2015 }
2016 else if (strcmp(args[cur_arg], "odd") == 0) {
2017 set |= 0x55555555;
2018 }
2019 else if (strcmp(args[cur_arg], "even") == 0) {
2020 set |= 0xAAAAAAAA;
2021 }
2022 else {
2023 u = str2uic(args[cur_arg]);
2024 if (u < 1 || u > 32) {
2025 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2026 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002029 }
2030 if (u > global.nbproc) {
2031 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2032 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002034 }
2035 set |= 1 << (u - 1);
2036 }
2037 cur_arg++;
2038 }
2039 curproxy->bind_proc = set;
2040 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002041 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002042 if (curproxy == &defproxy) {
2043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002046 }
2047
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002048 err = invalid_char(args[1]);
2049 if (err) {
2050 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2051 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002052 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002053 }
2054
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002055 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2056 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2057 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002058 err_code |= ERR_ALERT | ERR_FATAL;
2059 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002060 }
2061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2063 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002064
Willy Tarreau977b8e42006-12-29 14:19:17 +01002065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002066 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002067
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068 if (*(args[1]) == 0) {
2069 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2070 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002074
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002075 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002076 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002077 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002078 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002079 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 curproxy->cookie_name = strdup(args[1]);
2081 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002082
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 cur_arg = 2;
2084 while (*(args[cur_arg])) {
2085 if (!strcmp(args[cur_arg], "rewrite")) {
2086 curproxy->options |= PR_O_COOK_RW;
2087 }
2088 else if (!strcmp(args[cur_arg], "indirect")) {
2089 curproxy->options |= PR_O_COOK_IND;
2090 }
2091 else if (!strcmp(args[cur_arg], "insert")) {
2092 curproxy->options |= PR_O_COOK_INS;
2093 }
2094 else if (!strcmp(args[cur_arg], "nocache")) {
2095 curproxy->options |= PR_O_COOK_NOC;
2096 }
2097 else if (!strcmp(args[cur_arg], "postonly")) {
2098 curproxy->options |= PR_O_COOK_POST;
2099 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002100 else if (!strcmp(args[cur_arg], "preserve")) {
2101 curproxy->options2 |= PR_O2_COOK_PSV;
2102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 else if (!strcmp(args[cur_arg], "prefix")) {
2104 curproxy->options |= PR_O_COOK_PFX;
2105 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002106 else if (!strcmp(args[cur_arg], "domain")) {
2107 if (!*args[cur_arg + 1]) {
2108 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2109 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002112 }
2113
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002114 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002115 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002116 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2117 " dots nor does not start with a dot."
2118 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002119 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002120 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002121 }
2122
2123 err = invalid_domainchar(args[cur_arg + 1]);
2124 if (err) {
2125 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2126 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002129 }
2130
Willy Tarreau68a897b2009-12-03 23:28:34 +01002131 if (!curproxy->cookie_domain) {
2132 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2133 } else {
2134 /* one domain was already specified, add another one by
2135 * building the string which will be returned along with
2136 * the cookie.
2137 */
2138 char *new_ptr;
2139 int new_len = strlen(curproxy->cookie_domain) +
2140 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2141 new_ptr = malloc(new_len);
2142 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2143 free(curproxy->cookie_domain);
2144 curproxy->cookie_domain = new_ptr;
2145 }
Willy Tarreau31936852010-10-06 16:59:56 +02002146 cur_arg++;
2147 }
2148 else if (!strcmp(args[cur_arg], "maxidle")) {
2149 unsigned int maxidle;
2150 const char *res;
2151
2152 if (!*args[cur_arg + 1]) {
2153 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2154 file, linenum, args[cur_arg]);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158
2159 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2160 if (res) {
2161 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2162 file, linenum, *res, args[cur_arg]);
2163 err_code |= ERR_ALERT | ERR_FATAL;
2164 goto out;
2165 }
2166 curproxy->cookie_maxidle = maxidle;
2167 cur_arg++;
2168 }
2169 else if (!strcmp(args[cur_arg], "maxlife")) {
2170 unsigned int maxlife;
2171 const char *res;
2172
2173 if (!*args[cur_arg + 1]) {
2174 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2175 file, linenum, args[cur_arg]);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179
2180 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2181 if (res) {
2182 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2183 file, linenum, *res, args[cur_arg]);
2184 err_code |= ERR_ALERT | ERR_FATAL;
2185 goto out;
2186 }
2187 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002188 cur_arg++;
2189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002191 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 +02002192 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002195 }
2196 cur_arg++;
2197 }
2198 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2199 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2200 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002202 }
2203
2204 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2205 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2206 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002207 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002208 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002209
2210 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2211 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2212 file, linenum);
2213 err_code |= ERR_ALERT | ERR_FATAL;
2214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002216 else if (!strcmp(args[0], "persist")) { /* persist */
2217 if (*(args[1]) == 0) {
2218 Alert("parsing [%s:%d] : missing persist method.\n",
2219 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002222 }
2223
2224 if (!strncmp(args[1], "rdp-cookie", 10)) {
2225 curproxy->options2 |= PR_O2_RDPC_PRST;
2226
Emeric Brunb982a3d2010-01-04 15:45:53 +01002227 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002228 const char *beg, *end;
2229
2230 beg = args[1] + 11;
2231 end = strchr(beg, ')');
2232
2233 if (!end || end == beg) {
2234 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2235 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002236 err_code |= ERR_ALERT | ERR_FATAL;
2237 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002238 }
2239
2240 free(curproxy->rdp_cookie_name);
2241 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2242 curproxy->rdp_cookie_len = end-beg;
2243 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002244 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002245 free(curproxy->rdp_cookie_name);
2246 curproxy->rdp_cookie_name = strdup("msts");
2247 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2248 }
2249 else { /* syntax */
2250 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2251 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002254 }
2255 }
2256 else {
2257 Alert("parsing [%s:%d] : unknown persist method.\n",
2258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002261 }
2262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002264 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002266 if (curproxy == &defproxy) {
2267 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
2270 }
2271
Willy Tarreau977b8e42006-12-29 14:19:17 +01002272 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002274
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002276 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002278 err_code |= ERR_ALERT | ERR_FATAL;
2279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 }
2281 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002282 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 curproxy->appsession_name = strdup(args[1]);
2284 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2285 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002286 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2287 if (err) {
2288 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2289 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002292 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002293 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002294
Willy Tarreau51041c72007-09-09 21:56:53 +02002295 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2296 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002297 err_code |= ERR_ALERT | ERR_ABORT;
2298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002300
2301 cur_arg = 6;
2302 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002303 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2304 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002305 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002306 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002307 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002308 } else if (!strcmp(args[cur_arg], "prefix")) {
2309 curproxy->options2 |= PR_O2_AS_PFX;
2310 } else if (!strcmp(args[cur_arg], "mode")) {
2311 if (!*args[cur_arg + 1]) {
2312 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2313 file, linenum, args[0], args[cur_arg]);
2314 err_code |= ERR_ALERT | ERR_FATAL;
2315 goto out;
2316 }
2317
2318 cur_arg++;
2319 if (!strcmp(args[cur_arg], "query-string")) {
2320 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2321 curproxy->options2 |= PR_O2_AS_M_QS;
2322 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2323 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2324 curproxy->options2 |= PR_O2_AS_M_PP;
2325 } else {
2326 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2327 err_code |= ERR_ALERT | ERR_FATAL;
2328 goto out;
2329 }
2330 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002331 cur_arg++;
2332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 } /* Url App Session */
2334 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002335 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002337
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002339 if (curproxy == &defproxy) {
2340 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
2343 }
2344
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 if (*(args[4]) == 0) {
2346 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002351 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 curproxy->capture_name = strdup(args[2]);
2353 curproxy->capture_namelen = strlen(curproxy->capture_name);
2354 curproxy->capture_len = atol(args[4]);
2355 if (curproxy->capture_len >= CAPTURE_LEN) {
2356 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2357 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 curproxy->capture_len = CAPTURE_LEN - 1;
2360 }
2361 curproxy->to_log |= LW_COOKIE;
2362 }
2363 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2364 struct cap_hdr *hdr;
2365
2366 if (curproxy == &defproxy) {
2367 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 +02002368 err_code |= ERR_ALERT | ERR_FATAL;
2369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 }
2371
2372 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2373 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2374 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }
2378
2379 hdr = calloc(sizeof(struct cap_hdr), 1);
2380 hdr->next = curproxy->req_cap;
2381 hdr->name = strdup(args[3]);
2382 hdr->namelen = strlen(args[3]);
2383 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002384 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 hdr->index = curproxy->nb_req_cap++;
2386 curproxy->req_cap = hdr;
2387 curproxy->to_log |= LW_REQHDR;
2388 }
2389 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2390 struct cap_hdr *hdr;
2391
2392 if (curproxy == &defproxy) {
2393 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 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 }
2397
2398 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2399 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2400 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_ALERT | ERR_FATAL;
2402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 }
2404 hdr = calloc(sizeof(struct cap_hdr), 1);
2405 hdr->next = curproxy->rsp_cap;
2406 hdr->name = strdup(args[3]);
2407 hdr->namelen = strlen(args[3]);
2408 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002409 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 hdr->index = curproxy->nb_rsp_cap++;
2411 curproxy->rsp_cap = hdr;
2412 curproxy->to_log |= LW_RSPHDR;
2413 }
2414 else {
2415 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2416 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 }
2420 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 if (*(args[1]) == 0) {
2426 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2427 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431 curproxy->conn_retries = atol(args[1]);
2432 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002433 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002434 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002435
2436 if (curproxy == &defproxy) {
2437 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
2440 }
2441
Willy Tarreauff011f22011-01-06 17:51:27 +01002442 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 +01002443 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2444 file, linenum, args[0]);
2445 err_code |= ERR_WARN;
2446 }
2447
Willy Tarreauff011f22011-01-06 17:51:27 +01002448 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002449
Willy Tarreauff011f22011-01-06 17:51:27 +01002450 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002451 err_code |= ERR_ALERT | ERR_ABORT;
2452 goto out;
2453 }
2454
Willy Tarreauff011f22011-01-06 17:51:27 +01002455 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2456 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002457 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002458 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002459 if (curproxy == &defproxy) {
2460 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002463 }
2464
Willy Tarreauef6494c2010-01-28 17:12:36 +01002465 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002466 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2467 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002468 err_code |= ERR_ALERT | ERR_FATAL;
2469 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002470 }
2471
Willy Tarreauef6494c2010-01-28 17:12:36 +01002472 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002473 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2474 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002475 err_code |= ERR_ALERT | ERR_FATAL;
2476 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002477 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002478
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002479 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002480 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002481 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002482 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002483 struct redirect_rule *rule;
2484 int cur_arg;
2485 int type = REDIRECT_TYPE_NONE;
2486 int code = 302;
2487 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002488 char *cookie = NULL;
2489 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002490 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002491
Cyril Bonté99ed3272010-01-24 23:29:44 +01002492 if (curproxy == &defproxy) {
2493 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
2496 }
2497
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002498 cur_arg = 1;
2499 while (*(args[cur_arg])) {
2500 if (!strcmp(args[cur_arg], "location")) {
2501 if (!*args[cur_arg + 1]) {
2502 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2503 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002506 }
2507
2508 type = REDIRECT_TYPE_LOCATION;
2509 cur_arg++;
2510 destination = args[cur_arg];
2511 }
2512 else if (!strcmp(args[cur_arg], "prefix")) {
2513 if (!*args[cur_arg + 1]) {
2514 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2515 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002518 }
2519
2520 type = REDIRECT_TYPE_PREFIX;
2521 cur_arg++;
2522 destination = args[cur_arg];
2523 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002524 else if (!strcmp(args[cur_arg], "set-cookie")) {
2525 if (!*args[cur_arg + 1]) {
2526 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2527 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002530 }
2531
2532 cur_arg++;
2533 cookie = args[cur_arg];
2534 cookie_set = 1;
2535 }
2536 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2537 if (!*args[cur_arg + 1]) {
2538 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2539 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002542 }
2543
2544 cur_arg++;
2545 cookie = args[cur_arg];
2546 cookie_set = 0;
2547 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002548 else if (!strcmp(args[cur_arg],"code")) {
2549 if (!*args[cur_arg + 1]) {
2550 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2551 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002554 }
2555 cur_arg++;
2556 code = atol(args[cur_arg]);
2557 if (code < 301 || code > 303) {
2558 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2559 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_ALERT | ERR_FATAL;
2561 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002562 }
2563 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002564 else if (!strcmp(args[cur_arg],"drop-query")) {
2565 flags |= REDIRECT_FLAG_DROP_QS;
2566 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002567 else if (!strcmp(args[cur_arg],"append-slash")) {
2568 flags |= REDIRECT_FLAG_APPEND_SLASH;
2569 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002570 else if (strcmp(args[cur_arg], "if") == 0 ||
2571 strcmp(args[cur_arg], "unless") == 0) {
2572 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2573 if (!cond) {
2574 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2575 file, linenum, args[0]);
2576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
2578 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002579 break;
2580 }
2581 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002582 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 +02002583 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002584 err_code |= ERR_ALERT | ERR_FATAL;
2585 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002586 }
2587 cur_arg++;
2588 }
2589
2590 if (type == REDIRECT_TYPE_NONE) {
2591 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2592 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002595 }
2596
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002597 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2598 rule->cond = cond;
2599 rule->rdr_str = strdup(destination);
2600 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002601 if (cookie) {
2602 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002603 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002604 */
2605 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002606 if (cookie_set) {
2607 rule->cookie_str = malloc(rule->cookie_len + 10);
2608 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2609 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2610 rule->cookie_len += 9;
2611 } else {
2612 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002613 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002614 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2615 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002616 }
2617 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002618 rule->type = type;
2619 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002620 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002621 LIST_INIT(&rule->list);
2622 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002623 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2624 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002625 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002626 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002627 struct switching_rule *rule;
2628
Willy Tarreaub099aca2008-10-12 17:26:37 +02002629 if (curproxy == &defproxy) {
2630 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_FATAL;
2632 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002633 }
2634
Willy Tarreau55ea7572007-06-17 19:56:27 +02002635 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002636 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002637
2638 if (*(args[1]) == 0) {
2639 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002642 }
2643
Willy Tarreauef6494c2010-01-28 17:12:36 +01002644 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002645 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2646 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002647 err_code |= ERR_ALERT | ERR_FATAL;
2648 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002649 }
2650
Willy Tarreauef6494c2010-01-28 17:12:36 +01002651 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002652 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002653 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002656 }
2657
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002658 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002659
Willy Tarreau55ea7572007-06-17 19:56:27 +02002660 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2661 rule->cond = cond;
2662 rule->be.name = strdup(args[1]);
2663 LIST_INIT(&rule->list);
2664 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2665 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002666 else if ((!strcmp(args[0], "force-persist")) ||
2667 (!strcmp(args[0], "ignore-persist"))) {
2668 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002669
2670 if (curproxy == &defproxy) {
2671 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675
2676 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2677 err_code |= ERR_WARN;
2678
Willy Tarreauef6494c2010-01-28 17:12:36 +01002679 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002680 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2681 file, linenum, args[0]);
2682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
2684 }
2685
Willy Tarreauef6494c2010-01-28 17:12:36 +01002686 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002687 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2688 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
2691 }
2692
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002693 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002694
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002695 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002696 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002697 if (!strcmp(args[0], "force-persist")) {
2698 rule->type = PERSIST_TYPE_FORCE;
2699 } else {
2700 rule->type = PERSIST_TYPE_IGNORE;
2701 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002702 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002703 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002704 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002705 else if (!strcmp(args[0], "stick-table")) {
2706 int myidx = 1;
2707
Emeric Brun32da3c42010-09-23 18:39:19 +02002708 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002709 curproxy->table.type = (unsigned int)-1;
2710 while (*args[myidx]) {
2711 const char *err;
2712
2713 if (strcmp(args[myidx], "size") == 0) {
2714 myidx++;
2715 if (!*(args[myidx])) {
2716 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2717 file, linenum, args[myidx-1]);
2718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
2720 }
2721 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2722 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2723 file, linenum, *err, args[myidx-1]);
2724 err_code |= ERR_ALERT | ERR_FATAL;
2725 goto out;
2726 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002727 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002728 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002729 else if (strcmp(args[myidx], "peers") == 0) {
2730 myidx++;
2731 if (!*(args[myidx])) {
2732 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2733 file, linenum, args[myidx-1]);
2734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
2737 curproxy->table.peers.name = strdup(args[myidx++]);
2738 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002739 else if (strcmp(args[myidx], "expire") == 0) {
2740 myidx++;
2741 if (!*(args[myidx])) {
2742 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2743 file, linenum, args[myidx-1]);
2744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
2746 }
2747 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2748 if (err) {
2749 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2750 file, linenum, *err, args[myidx-1]);
2751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
2753 }
2754 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002755 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002756 }
2757 else if (strcmp(args[myidx], "nopurge") == 0) {
2758 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002759 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002760 }
2761 else if (strcmp(args[myidx], "type") == 0) {
2762 myidx++;
2763 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2764 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2765 file, linenum, args[myidx]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002769 /* myidx already points to next arg */
2770 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002771 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002772 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002773 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002774
2775 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002776 nw = args[myidx];
2777 while (*nw) {
2778 /* the "store" keyword supports a comma-separated list */
2779 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002780 sa = NULL; /* store arg */
2781 while (*nw && *nw != ',') {
2782 if (*nw == '(') {
2783 *nw = 0;
2784 sa = ++nw;
2785 while (*nw != ')') {
2786 if (!*nw) {
2787 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2788 file, linenum, args[0], cw);
2789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
2791 }
2792 nw++;
2793 }
2794 *nw = '\0';
2795 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002796 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002797 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002798 if (*nw)
2799 *nw++ = '\0';
2800 type = stktable_get_data_type(cw);
2801 if (type < 0) {
2802 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2803 file, linenum, args[0], cw);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
Willy Tarreauac782882010-06-20 10:41:54 +02002807
2808 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2809 switch (err) {
2810 case PE_NONE: break;
2811 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002812 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2813 file, linenum, args[0], cw);
2814 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002815 break;
2816
2817 case PE_ARG_MISSING:
2818 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2819 file, linenum, args[0], cw);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822
2823 case PE_ARG_NOT_USED:
2824 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2825 file, linenum, args[0], cw);
2826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
2828
2829 default:
2830 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2831 file, linenum, args[0], cw);
2832 err_code |= ERR_ALERT | ERR_FATAL;
2833 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002834 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002835 }
2836 myidx++;
2837 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002838 else {
2839 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2840 file, linenum, args[myidx]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002843 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002844 }
2845
2846 if (!curproxy->table.size) {
2847 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2848 file, linenum);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852
2853 if (curproxy->table.type == (unsigned int)-1) {
2854 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2855 file, linenum);
2856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859 }
2860 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002861 struct sticking_rule *rule;
2862 struct pattern_expr *expr;
2863 int myidx = 0;
2864 const char *name = NULL;
2865 int flags;
2866
2867 if (curproxy == &defproxy) {
2868 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872
2873 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2874 err_code |= ERR_WARN;
2875 goto out;
2876 }
2877
2878 myidx++;
2879 if ((strcmp(args[myidx], "store") == 0) ||
2880 (strcmp(args[myidx], "store-request") == 0)) {
2881 myidx++;
2882 flags = STK_IS_STORE;
2883 }
2884 else if (strcmp(args[myidx], "store-response") == 0) {
2885 myidx++;
2886 flags = STK_IS_STORE | STK_ON_RSP;
2887 }
2888 else if (strcmp(args[myidx], "match") == 0) {
2889 myidx++;
2890 flags = STK_IS_MATCH;
2891 }
2892 else if (strcmp(args[myidx], "on") == 0) {
2893 myidx++;
2894 flags = STK_IS_MATCH | STK_IS_STORE;
2895 }
2896 else {
2897 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900 }
2901
2902 if (*(args[myidx]) == 0) {
2903 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2904 err_code |= ERR_ALERT | ERR_FATAL;
2905 goto out;
2906 }
2907
Emeric Brun485479d2010-09-23 18:02:19 +02002908 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002909 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002910 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
2914
2915 if (flags & STK_ON_RSP) {
2916 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2917 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2918 file, linenum, args[0], expr->fetch->kw);
2919 err_code |= ERR_ALERT | ERR_FATAL;
2920 goto out;
2921 }
2922 } else {
2923 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2924 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2925 file, linenum, args[0], expr->fetch->kw);
2926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
2929 }
2930
2931 if (strcmp(args[myidx], "table") == 0) {
2932 myidx++;
2933 name = args[myidx++];
2934 }
2935
Willy Tarreauef6494c2010-01-28 17:12:36 +01002936 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2937 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2939 file, linenum, args[0]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002943 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002944 else if (*(args[myidx])) {
2945 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2946 file, linenum, args[0], args[myidx]);
2947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
2949 }
Emeric Brun97679e72010-09-23 17:56:44 +02002950 if (flags & STK_ON_RSP)
2951 err_code |= warnif_cond_requires_req(cond, file, linenum);
2952 else
2953 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002954
Emeric Brunb982a3d2010-01-04 15:45:53 +01002955 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2956 rule->cond = cond;
2957 rule->expr = expr;
2958 rule->flags = flags;
2959 rule->table.name = name ? strdup(name) : NULL;
2960 LIST_INIT(&rule->list);
2961 if (flags & STK_ON_RSP)
2962 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2963 else
2964 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002967 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002968 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002969
Willy Tarreaubaaee002006-06-26 02:48:02 +02002970 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2971 curproxy->uri_auth = NULL; /* we must detach from the default config */
2972
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002973 if (!*args[1]) {
2974 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02002975 } else if (!strcmp(args[1], "admin")) {
2976 struct stats_admin_rule *rule;
2977
2978 if (curproxy == &defproxy) {
2979 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
2982 }
2983
2984 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2985 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2986 err_code |= ERR_ALERT | ERR_ABORT;
2987 goto out;
2988 }
2989
2990 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2991 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2992 file, linenum, args[0], args[1]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2997 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
2998 file, linenum, args[0], args[1]);
2999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002
3003 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3004
3005 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3006 rule->cond = cond;
3007 LIST_INIT(&rule->list);
3008 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 } else if (!strcmp(args[1], "uri")) {
3010 if (*(args[2]) == 0) {
3011 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3015 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_ALERT | ERR_ABORT;
3017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 }
3019 } else if (!strcmp(args[1], "realm")) {
3020 if (*(args[2]) == 0) {
3021 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003024 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3025 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_ALERT | ERR_ABORT;
3027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003029 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003030 unsigned interval;
3031
3032 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3033 if (err) {
3034 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3035 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003038 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3039 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003040 err_code |= ERR_ALERT | ERR_ABORT;
3041 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003042 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003043 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003044 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003045
3046 if (curproxy == &defproxy) {
3047 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
3050 }
3051
3052 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3053 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3054 err_code |= ERR_ALERT | ERR_ABORT;
3055 goto out;
3056 }
3057
Willy Tarreauff011f22011-01-06 17:51:27 +01003058 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3059 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003060 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3061 file, linenum, args[0]);
3062 err_code |= ERR_WARN;
3063 }
3064
Willy Tarreauff011f22011-01-06 17:51:27 +01003065 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003066
Willy Tarreauff011f22011-01-06 17:51:27 +01003067 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003068 err_code |= ERR_ALERT | ERR_ABORT;
3069 goto out;
3070 }
3071
Willy Tarreauff011f22011-01-06 17:51:27 +01003072 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3073 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003074
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 } else if (!strcmp(args[1], "auth")) {
3076 if (*(args[2]) == 0) {
3077 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003078 err_code |= ERR_ALERT | ERR_FATAL;
3079 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3081 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_ALERT | ERR_ABORT;
3083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003084 }
3085 } else if (!strcmp(args[1], "scope")) {
3086 if (*(args[2]) == 0) {
3087 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3091 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_ALERT | ERR_ABORT;
3093 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 }
3095 } else if (!strcmp(args[1], "enable")) {
3096 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3097 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003098 err_code |= ERR_ALERT | ERR_ABORT;
3099 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003101 } else if (!strcmp(args[1], "hide-version")) {
3102 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3103 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003104 err_code |= ERR_ALERT | ERR_ABORT;
3105 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003106 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003107 } else if (!strcmp(args[1], "show-legends")) {
3108 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3109 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3110 err_code |= ERR_ALERT | ERR_ABORT;
3111 goto out;
3112 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003113 } else if (!strcmp(args[1], "show-node")) {
3114
3115 if (*args[2]) {
3116 int i;
3117 char c;
3118
3119 for (i=0; args[2][i]; i++) {
3120 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003121 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3122 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003123 break;
3124 }
3125
3126 if (!i || args[2][i]) {
3127 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3128 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3129 file, linenum, args[0], args[1]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133 }
3134
3135 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3136 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3137 err_code |= ERR_ALERT | ERR_ABORT;
3138 goto out;
3139 }
3140 } else if (!strcmp(args[1], "show-desc")) {
3141 char *desc = NULL;
3142
3143 if (*args[2]) {
3144 int i, len=0;
3145 char *d;
3146
3147 for(i=2; *args[i]; i++)
3148 len += strlen(args[i])+1;
3149
3150 desc = d = (char *)calloc(1, len);
3151
3152 d += sprintf(d, "%s", args[2]);
3153 for(i=3; *args[i]; i++)
3154 d += sprintf(d, " %s", args[i]);
3155 }
3156
3157 if (!*args[2] && !global.desc)
3158 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3159 file, linenum, args[1]);
3160 else {
3161 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3162 free(desc);
3163 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3164 err_code |= ERR_ALERT | ERR_ABORT;
3165 goto out;
3166 }
3167 free(desc);
3168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003170stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003171 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 +01003172 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 }
3176 }
3177 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003178 int optnum;
3179
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003180 if (*(args[1]) == '\0') {
3181 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3182 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003186
3187 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3188 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003189 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3190 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3191 file, linenum, cfg_opts[optnum].name);
3192 err_code |= ERR_ALERT | ERR_FATAL;
3193 goto out;
3194 }
Willy Tarreau93893792009-07-23 13:19:11 +02003195 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3196 err_code |= ERR_WARN;
3197 goto out;
3198 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003199
Willy Tarreau3842f002009-06-14 11:39:52 +02003200 curproxy->no_options &= ~cfg_opts[optnum].val;
3201 curproxy->options &= ~cfg_opts[optnum].val;
3202
3203 switch (kwm) {
3204 case KWM_STD:
3205 curproxy->options |= cfg_opts[optnum].val;
3206 break;
3207 case KWM_NO:
3208 curproxy->no_options |= cfg_opts[optnum].val;
3209 break;
3210 case KWM_DEF: /* already cleared */
3211 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003212 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003213
Willy Tarreau93893792009-07-23 13:19:11 +02003214 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003215 }
3216 }
3217
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003218 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3219 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003220 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3221 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3222 file, linenum, cfg_opts2[optnum].name);
3223 err_code |= ERR_ALERT | ERR_FATAL;
3224 goto out;
3225 }
Willy Tarreau93893792009-07-23 13:19:11 +02003226 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3227 err_code |= ERR_WARN;
3228 goto out;
3229 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003230
Willy Tarreau3842f002009-06-14 11:39:52 +02003231 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3232 curproxy->options2 &= ~cfg_opts2[optnum].val;
3233
3234 switch (kwm) {
3235 case KWM_STD:
3236 curproxy->options2 |= cfg_opts2[optnum].val;
3237 break;
3238 case KWM_NO:
3239 curproxy->no_options2 |= cfg_opts2[optnum].val;
3240 break;
3241 case KWM_DEF: /* already cleared */
3242 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003243 }
Willy Tarreau93893792009-07-23 13:19:11 +02003244 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003245 }
3246 }
3247
Willy Tarreau3842f002009-06-14 11:39:52 +02003248 if (kwm != KWM_STD) {
3249 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003250 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003253 }
3254
Emeric Brun3a058f32009-06-30 18:26:00 +02003255 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003257 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02003259 if (*(args[2]) != '\0') {
3260 if (!strcmp(args[2], "clf")) {
3261 curproxy->options2 |= PR_O2_CLFLOG;
3262 } else {
3263 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003266 }
3267 }
3268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 else if (!strcmp(args[1], "tcplog"))
3270 /* generate a detailed TCP log */
3271 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 else if (!strcmp(args[1], "tcpka")) {
3273 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003274 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003276
3277 if (curproxy->cap & PR_CAP_FE)
3278 curproxy->options |= PR_O_TCP_CLI_KA;
3279 if (curproxy->cap & PR_CAP_BE)
3280 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
3282 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003283 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_WARN;
3285
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003287 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003288 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003289 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003290 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003291 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003292 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003293 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003294 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 if (!*args[2]) { /* no argument */
3296 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3297 curproxy->check_len = strlen(DEF_CHECK_REQ);
3298 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003299 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 curproxy->check_req = (char *)malloc(reqlen);
3301 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003302 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003304 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 if (*args[4])
3306 reqlen += strlen(args[4]);
3307 else
3308 reqlen += strlen("HTTP/1.0");
3309
3310 curproxy->check_req = (char *)malloc(reqlen);
3311 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003312 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003314 }
3315 else if (!strcmp(args[1], "ssl-hello-chk")) {
3316 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003317 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003318 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003319
Willy Tarreaua534fea2008-08-03 12:19:50 +02003320 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003321 curproxy->check_req = NULL;
Willy Tarreauf3c69202006-07-09 16:42:34 +02003322 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003323 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003324 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003325 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003326 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003327 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 }
Willy Tarreau23677902007-05-08 23:50:35 +02003329 else if (!strcmp(args[1], "smtpchk")) {
3330 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003331 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003332 curproxy->check_req = NULL;
Willy Tarreau23677902007-05-08 23:50:35 +02003333 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003334 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003335 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003336 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003337 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003338 curproxy->options |= PR_O_SMTP_CHK;
3339
3340 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3341 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3342 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3343 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3344 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3345 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3346 curproxy->check_req = (char *)malloc(reqlen);
3347 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3348 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3349 } else {
3350 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3351 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3352 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3353 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3354 }
3355 }
3356 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003357 else if (!strcmp(args[1], "pgsql-check")) {
3358 /* use PostgreSQL request to check servers' health */
3359 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3360 err_code |= ERR_WARN;
3361
3362 free(curproxy->check_req);
3363 curproxy->check_req = NULL;
3364 curproxy->options &= ~PR_O_HTTP_CHK;
3365 curproxy->options &= ~PR_O_SMTP_CHK;
3366 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3367 curproxy->options2 &= ~PR_O2_LDAP_CHK;
3368 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
3369 curproxy->options2 |= PR_O2_PGSQL_CHK;
3370
3371 if (*(args[2])) {
3372 int cur_arg = 2;
3373
3374 while (*(args[cur_arg])) {
3375 if (strcmp(args[cur_arg], "user") == 0) {
3376 char * packet;
3377 uint32_t packet_len;
3378 uint32_t pv;
3379
3380 /* suboption header - needs additional argument for it */
3381 if (*(args[cur_arg+1]) == 0) {
3382 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3383 file, linenum, args[0], args[1], args[cur_arg]);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
3387
3388 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3389 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3390 pv = htonl(0x30000); /* protocol version 3.0 */
3391
3392 packet = (char*) calloc(1, packet_len);
3393
3394 memcpy(packet + 4, &pv, 4);
3395
3396 /* copy "user" */
3397 memcpy(packet + 8, "user", 4);
3398
3399 /* copy username */
3400 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3401
3402 free(curproxy->check_req);
3403 curproxy->check_req = packet;
3404 curproxy->check_len = packet_len;
3405
3406 packet_len = htonl(packet_len);
3407 memcpy(packet, &packet_len, 4);
3408 cur_arg += 2;
3409 } else {
3410 /* unknown suboption - catchall */
3411 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3412 file, linenum, args[0], args[1]);
3413 err_code |= ERR_ALERT | ERR_FATAL;
3414 goto out;
3415 }
3416 } /* end while loop */
3417 }
3418 }
3419
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003420 else if (!strcmp(args[1], "mysql-check")) {
3421 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003422 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3423 err_code |= ERR_WARN;
3424
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003425 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003426 curproxy->check_req = NULL;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003427 curproxy->options &= ~PR_O_HTTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003428 curproxy->options &= ~PR_O_SMTP_CHK;
Willy Tarreau07a54902010-03-29 18:33:29 +02003429 curproxy->options2 &= ~PR_O2_SSL3_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003430 curproxy->options2 &= ~PR_O2_LDAP_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003431 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003432 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003433
3434 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3435 * const char mysql40_client_auth_pkt[] = {
3436 * "\x0e\x00\x00" // packet length
3437 * "\x01" // packet number
3438 * "\x00\x00" // client capabilities
3439 * "\x00\x00\x01" // max packet
3440 * "haproxy\x00" // username (null terminated string)
3441 * "\x00" // filler (always 0x00)
3442 * "\x01\x00\x00" // packet length
3443 * "\x00" // packet number
3444 * "\x01" // COM_QUIT command
3445 * };
3446 */
3447
3448 if (*(args[2])) {
3449 int cur_arg = 2;
3450
3451 while (*(args[cur_arg])) {
3452 if (strcmp(args[cur_arg], "user") == 0) {
3453 char *mysqluser;
3454 int packetlen, reqlen, userlen;
3455
3456 /* suboption header - needs additional argument for it */
3457 if (*(args[cur_arg+1]) == 0) {
3458 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3459 file, linenum, args[0], args[1], args[cur_arg]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463 mysqluser = args[cur_arg + 1];
3464 userlen = strlen(mysqluser);
3465 packetlen = userlen + 7;
3466 reqlen = packetlen + 9;
3467
3468 free(curproxy->check_req);
3469 curproxy->check_req = (char *)calloc(1, reqlen);
3470 curproxy->check_len = reqlen;
3471
3472 snprintf(curproxy->check_req, 4, "%c%c%c",
3473 ((unsigned char) packetlen & 0xff),
3474 ((unsigned char) (packetlen >> 8) & 0xff),
3475 ((unsigned char) (packetlen >> 16) & 0xff));
3476
3477 curproxy->check_req[3] = 1;
3478 curproxy->check_req[8] = 1;
3479 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3480 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3481 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3482 cur_arg += 2;
3483 } else {
3484 /* unknown suboption - catchall */
3485 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3486 file, linenum, args[0], args[1]);
3487 err_code |= ERR_ALERT | ERR_FATAL;
3488 goto out;
3489 }
3490 } /* end while loop */
3491 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003492 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003493 else if (!strcmp(args[1], "ldap-check")) {
3494 /* use LDAP request to check servers' health */
3495 free(curproxy->check_req);
3496 curproxy->check_req = NULL;
3497 curproxy->options &= ~PR_O_HTTP_CHK;
3498 curproxy->options &= ~PR_O_SMTP_CHK;
3499 curproxy->options2 &= ~PR_O2_SSL3_CHK;
3500 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003501 curproxy->options2 &= ~PR_O2_PGSQL_CHK;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003502 curproxy->options2 |= PR_O2_LDAP_CHK;
3503
3504 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3505 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3506 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3507 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003508 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003509 int cur_arg;
3510
3511 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3512 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003513 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003514
3515 curproxy->options |= PR_O_FWDFOR;
3516
3517 free(curproxy->fwdfor_hdr_name);
3518 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3519 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3520
3521 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3522 cur_arg = 2;
3523 while (*(args[cur_arg])) {
3524 if (!strcmp(args[cur_arg], "except")) {
3525 /* suboption except - needs additional argument for it */
3526 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3527 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3528 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003531 }
3532 /* flush useless bits */
3533 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003534 cur_arg += 2;
3535 } else if (!strcmp(args[cur_arg], "header")) {
3536 /* suboption header - needs additional argument for it */
3537 if (*(args[cur_arg+1]) == 0) {
3538 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3539 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_FATAL;
3541 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003542 }
3543 free(curproxy->fwdfor_hdr_name);
3544 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3545 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3546 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003547 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003548 /* unknown suboption - catchall */
3549 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3550 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003553 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003554 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003555 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003556 else if (!strcmp(args[1], "originalto")) {
3557 int cur_arg;
3558
3559 /* insert x-original-to field, but not for the IP address listed as an except.
3560 * set default options (ie: bitfield, header name, etc)
3561 */
3562
3563 curproxy->options |= PR_O_ORGTO;
3564
3565 free(curproxy->orgto_hdr_name);
3566 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3567 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3568
3569 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3570 cur_arg = 2;
3571 while (*(args[cur_arg])) {
3572 if (!strcmp(args[cur_arg], "except")) {
3573 /* suboption except - needs additional argument for it */
3574 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3575 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3576 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003579 }
3580 /* flush useless bits */
3581 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3582 cur_arg += 2;
3583 } else if (!strcmp(args[cur_arg], "header")) {
3584 /* suboption header - needs additional argument for it */
3585 if (*(args[cur_arg+1]) == 0) {
3586 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3587 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003590 }
3591 free(curproxy->orgto_hdr_name);
3592 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3593 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3594 cur_arg += 2;
3595 } else {
3596 /* unknown suboption - catchall */
3597 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3598 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003601 }
3602 } /* end while loop */
3603 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003604 else {
3605 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
3607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 }
Willy Tarreau93893792009-07-23 13:19:11 +02003609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003610 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003611 else if (!strcmp(args[0], "default_backend")) {
3612 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003614
3615 if (*(args[1]) == 0) {
3616 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003619 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003620 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003621 curproxy->defbe.name = strdup(args[1]);
3622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003626
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003627 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 /* enable reconnections to dispatch */
3631 curproxy->options |= PR_O_REDISP;
3632 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003633 else if (!strcmp(args[0], "http-check")) {
3634 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003636
3637 if (strcmp(args[1], "disable-on-404") == 0) {
3638 /* enable a graceful server shutdown on an HTTP 404 response */
3639 curproxy->options |= PR_O_DISABLE404;
3640 }
Willy Tarreauef781042010-01-27 11:53:01 +01003641 else if (strcmp(args[1], "send-state") == 0) {
3642 /* enable emission of the apparent state of a server in HTTP checks */
3643 curproxy->options2 |= PR_O2_CHK_SNDST;
3644 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003645 else if (strcmp(args[1], "expect") == 0) {
3646 const char *ptr_arg;
3647 int cur_arg;
3648
3649 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3650 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
3653 }
3654
3655 cur_arg = 2;
3656 /* consider exclamation marks, sole or at the beginning of a word */
3657 while (*(ptr_arg = args[cur_arg])) {
3658 while (*ptr_arg == '!') {
3659 curproxy->options2 ^= PR_O2_EXP_INV;
3660 ptr_arg++;
3661 }
3662 if (*ptr_arg)
3663 break;
3664 cur_arg++;
3665 }
3666 /* now ptr_arg points to the beginning of a word past any possible
3667 * exclamation mark, and cur_arg is the argument which holds this word.
3668 */
3669 if (strcmp(ptr_arg, "status") == 0) {
3670 if (!*(args[cur_arg + 1])) {
3671 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3672 file, linenum, args[0], args[1], ptr_arg);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676 curproxy->options2 |= PR_O2_EXP_STS;
3677 curproxy->expect_str = strdup(args[cur_arg + 1]);
3678 }
3679 else if (strcmp(ptr_arg, "string") == 0) {
3680 if (!*(args[cur_arg + 1])) {
3681 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3682 file, linenum, args[0], args[1], ptr_arg);
3683 err_code |= ERR_ALERT | ERR_FATAL;
3684 goto out;
3685 }
3686 curproxy->options2 |= PR_O2_EXP_STR;
3687 curproxy->expect_str = strdup(args[cur_arg + 1]);
3688 }
3689 else if (strcmp(ptr_arg, "rstatus") == 0) {
3690 if (!*(args[cur_arg + 1])) {
3691 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3692 file, linenum, args[0], args[1], ptr_arg);
3693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
3695 }
3696 curproxy->options2 |= PR_O2_EXP_RSTS;
3697 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3698 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3699 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3700 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
3703 }
3704 }
3705 else if (strcmp(ptr_arg, "rstring") == 0) {
3706 if (!*(args[cur_arg + 1])) {
3707 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3708 file, linenum, args[0], args[1], ptr_arg);
3709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
3711 }
3712 curproxy->options2 |= PR_O2_EXP_RSTR;
3713 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3714 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3715 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3716 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
3719 }
3720 }
3721 else {
3722 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3723 file, linenum, args[0], args[1], ptr_arg);
3724 err_code |= ERR_ALERT | ERR_FATAL;
3725 goto out;
3726 }
3727 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003728 else {
Willy Tarreaubd741542010-03-16 18:46:54 +01003729 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'expect' .\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003732 }
3733 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003734 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003735 if (curproxy == &defproxy) {
3736 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003739 }
3740
Willy Tarreaub80c2302007-11-30 20:51:32 +01003741 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003742 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003743
3744 if (strcmp(args[1], "fail") == 0) {
3745 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003746 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003747 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3748 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003749 err_code |= ERR_ALERT | ERR_FATAL;
3750 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003751 }
3752
Willy Tarreauef6494c2010-01-28 17:12:36 +01003753 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003754 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3755 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003758 }
3759 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3760 }
3761 else {
3762 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003765 }
3766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767#ifdef TPROXY
3768 else if (!strcmp(args[0], "transparent")) {
3769 /* enable transparent proxy connections */
3770 curproxy->options |= PR_O_TRANSP;
3771 }
3772#endif
3773 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003776
Willy Tarreaubaaee002006-06-26 02:48:02 +02003777 if (*(args[1]) == 0) {
3778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 }
3782 curproxy->maxconn = atol(args[1]);
3783 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003784 else if (!strcmp(args[0], "backlog")) { /* backlog */
3785 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003787
3788 if (*(args[1]) == 0) {
3789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003792 }
3793 curproxy->backlog = atol(args[1]);
3794 }
Willy Tarreau86034312006-12-29 00:10:33 +01003795 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003797 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003798
Willy Tarreau86034312006-12-29 00:10:33 +01003799 if (*(args[1]) == 0) {
3800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003803 }
3804 curproxy->fullconn = atol(args[1]);
3805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003806 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3807 if (*(args[1]) == 0) {
3808 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003809 err_code |= ERR_ALERT | ERR_FATAL;
3810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003811 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003812 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3813 if (err) {
3814 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3815 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003818 }
3819 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 }
3821 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003822 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 if (curproxy == &defproxy) {
3824 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003827 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003828 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003829 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003830
Willy Tarreaubaaee002006-06-26 02:48:02 +02003831 if (strchr(args[1], ':') == NULL) {
3832 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003833 err_code |= ERR_ALERT | ERR_FATAL;
3834 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003835 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003836 sk = str2sa(args[1]);
3837 if (!sk) {
3838 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842 curproxy->dispatch_addr = *sk;
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01003843 curproxy->options2 |= PR_O2_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 }
3845 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003846 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003847 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003848
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003849 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003850 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3851 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003855 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003856 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3857 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3858 err_code |= ERR_WARN;
3859
3860 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3861 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3862 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3863 }
3864 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3865 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3866 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3867 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003868 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3869 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3870 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3871 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003872 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003873 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
3876 }
3877 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003878 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003880 char *rport, *raddr;
3881 short realport = 0;
3882 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003883
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003884 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003889 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891
3892 if (!*args[2]) {
3893 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3894 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003895 err_code |= ERR_ALERT | ERR_FATAL;
3896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003898
3899 err = invalid_char(args[1]);
3900 if (err) {
3901 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3902 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_ALERT | ERR_FATAL;
3904 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003905 }
3906
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003907 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003908 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003909
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003910 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3911 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3912 err_code |= ERR_ALERT | ERR_ABORT;
3913 goto out;
3914 }
3915
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003916 /* the servers are linked backwards first */
3917 newsrv->next = curproxy->srv;
3918 curproxy->srv = newsrv;
3919 newsrv->proxy = curproxy;
3920 newsrv->conf.file = file;
3921 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003923 LIST_INIT(&newsrv->pendconns);
3924 do_check = 0;
3925 newsrv->state = SRV_RUNNING; /* early server setup */
3926 newsrv->last_change = now.tv_sec;
3927 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003928
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003929 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003930 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003931 * - IP: => port=+0, relative
3932 * - IP:N => port=N, absolute
3933 * - IP:+N => port=+N, relative
3934 * - IP:-N => port=-N, relative
3935 */
3936 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003937 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003938 if (rport) {
3939 *rport++ = 0;
3940 realport = atol(rport);
3941 if (!isdigit((unsigned char)*rport))
3942 newsrv->state |= SRV_MAPPORTS;
3943 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003944 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003945
Willy Tarreaufab5a432011-03-04 15:31:53 +01003946 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003947 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01003948 if (!sk) {
3949 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
3950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
3952 }
3953 newsrv->addr = *sk;
David du Colombier6f5ccb12011-03-10 22:26:24 +01003954
3955 switch (newsrv->addr.ss_family) {
3956 case AF_INET:
3957 ((struct sockaddr_in *)&newsrv->addr)->sin_port = htons(realport);
3958 break;
3959 case AF_INET6:
3960 ((struct sockaddr_in6 *)&newsrv->addr)->sin6_port = htons(realport);
3961 break;
3962 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003963
3964 newsrv->check_port = curproxy->defsrv.check_port;
3965 newsrv->inter = curproxy->defsrv.inter;
3966 newsrv->fastinter = curproxy->defsrv.fastinter;
3967 newsrv->downinter = curproxy->defsrv.downinter;
3968 newsrv->rise = curproxy->defsrv.rise;
3969 newsrv->fall = curproxy->defsrv.fall;
3970 newsrv->maxqueue = curproxy->defsrv.maxqueue;
3971 newsrv->minconn = curproxy->defsrv.minconn;
3972 newsrv->maxconn = curproxy->defsrv.maxconn;
3973 newsrv->slowstart = curproxy->defsrv.slowstart;
3974 newsrv->onerror = curproxy->defsrv.onerror;
3975 newsrv->consecutive_errors_limit
3976 = curproxy->defsrv.consecutive_errors_limit;
3977 newsrv->uweight = newsrv->iweight
3978 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003979
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003980 newsrv->curfd = -1; /* no health-check in progress */
3981 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003982
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003983 cur_arg = 3;
3984 } else {
3985 newsrv = &curproxy->defsrv;
3986 cur_arg = 1;
3987 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003988
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003990 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003991 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003992
3993 if (!*args[cur_arg + 1]) {
3994 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3995 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003998 }
3999
4000 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004001 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004002
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004003 if (newsrv->puid <= 0) {
4004 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004005 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004008 }
4009
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004010 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4011 if (node) {
4012 struct server *target = container_of(node, struct server, conf.id);
4013 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4014 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004019 cur_arg += 2;
4020 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004021 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004022 newsrv->cookie = strdup(args[cur_arg + 1]);
4023 newsrv->cklen = strlen(args[cur_arg + 1]);
4024 cur_arg += 2;
4025 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004026 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004027 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4028 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4029 cur_arg += 2;
4030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004032 if (!*args[cur_arg + 1]) {
4033 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4034 file, linenum, args[cur_arg]);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 }
4038
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004040 if (newsrv->rise <= 0) {
4041 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4042 file, linenum, args[cur_arg]);
4043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
4045 }
4046
Willy Tarreau96839092010-03-29 10:02:24 +02004047 if (newsrv->health)
4048 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 cur_arg += 2;
4050 }
4051 else if (!strcmp(args[cur_arg], "fall")) {
4052 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004053
4054 if (!*args[cur_arg + 1]) {
4055 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4056 file, linenum, args[cur_arg]);
4057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
4059 }
4060
4061 if (newsrv->fall <= 0) {
4062 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4063 file, linenum, args[cur_arg]);
4064 err_code |= ERR_ALERT | ERR_FATAL;
4065 goto out;
4066 }
4067
Willy Tarreaubaaee002006-06-26 02:48:02 +02004068 cur_arg += 2;
4069 }
4070 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004071 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4072 if (err) {
4073 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4074 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004077 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004078 if (val <= 0) {
4079 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4080 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004083 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004084 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004085 cur_arg += 2;
4086 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004087 else if (!strcmp(args[cur_arg], "fastinter")) {
4088 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4089 if (err) {
4090 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4091 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004094 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004095 if (val <= 0) {
4096 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4097 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004098 err_code |= ERR_ALERT | ERR_FATAL;
4099 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004100 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004101 newsrv->fastinter = val;
4102 cur_arg += 2;
4103 }
4104 else if (!strcmp(args[cur_arg], "downinter")) {
4105 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4106 if (err) {
4107 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4108 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004111 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004112 if (val <= 0) {
4113 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4114 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004117 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004118 newsrv->downinter = val;
4119 cur_arg += 2;
4120 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004121 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004122 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004123 if (!sk) {
4124 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
4127 }
4128 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004129 cur_arg += 2;
4130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 else if (!strcmp(args[cur_arg], "port")) {
4132 newsrv->check_port = atol(args[cur_arg + 1]);
4133 cur_arg += 2;
4134 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004135 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 newsrv->state |= SRV_BACKUP;
4137 cur_arg ++;
4138 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004139 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4140 newsrv->state |= SRV_SEND_PROXY;
4141 cur_arg ++;
4142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 else if (!strcmp(args[cur_arg], "weight")) {
4144 int w;
4145 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004146 if (w < 0 || w > 256) {
4147 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004152 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 cur_arg += 2;
4154 }
4155 else if (!strcmp(args[cur_arg], "minconn")) {
4156 newsrv->minconn = atol(args[cur_arg + 1]);
4157 cur_arg += 2;
4158 }
4159 else if (!strcmp(args[cur_arg], "maxconn")) {
4160 newsrv->maxconn = atol(args[cur_arg + 1]);
4161 cur_arg += 2;
4162 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004163 else if (!strcmp(args[cur_arg], "maxqueue")) {
4164 newsrv->maxqueue = atol(args[cur_arg + 1]);
4165 cur_arg += 2;
4166 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004167 else if (!strcmp(args[cur_arg], "slowstart")) {
4168 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004169 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004170 if (err) {
4171 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4172 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_ALERT | ERR_FATAL;
4174 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004175 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004176 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004177 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4178 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004179 err_code |= ERR_ALERT | ERR_FATAL;
4180 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004181 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004182 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004183 cur_arg += 2;
4184 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004185 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004186
4187 if (!*args[cur_arg + 1]) {
4188 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4189 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004192 }
4193
4194 newsrv->trackit = strdup(args[cur_arg + 1]);
4195
4196 cur_arg += 2;
4197 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004198 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 global.maxsock++;
4200 do_check = 1;
4201 cur_arg += 1;
4202 }
Willy Tarreau96839092010-03-29 10:02:24 +02004203 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4204 newsrv->state |= SRV_MAINTAIN;
4205 newsrv->state &= ~SRV_RUNNING;
4206 newsrv->health = 0;
4207 cur_arg += 1;
4208 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004209 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004210 if (!strcmp(args[cur_arg + 1], "none"))
4211 newsrv->observe = HANA_OBS_NONE;
4212 else if (!strcmp(args[cur_arg + 1], "layer4"))
4213 newsrv->observe = HANA_OBS_LAYER4;
4214 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4215 if (curproxy->mode != PR_MODE_HTTP) {
4216 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4217 file, linenum, args[cur_arg + 1]);
4218 err_code |= ERR_ALERT;
4219 }
4220 newsrv->observe = HANA_OBS_LAYER7;
4221 }
4222 else {
4223 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004224 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004225 file, linenum, args[cur_arg], args[cur_arg + 1]);
4226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
4228 }
4229
4230 cur_arg += 2;
4231 }
4232 else if (!strcmp(args[cur_arg], "on-error")) {
4233 if (!strcmp(args[cur_arg + 1], "fastinter"))
4234 newsrv->onerror = HANA_ONERR_FASTINTER;
4235 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4236 newsrv->onerror = HANA_ONERR_FAILCHK;
4237 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4238 newsrv->onerror = HANA_ONERR_SUDDTH;
4239 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4240 newsrv->onerror = HANA_ONERR_MARKDWN;
4241 else {
4242 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004243 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004244 file, linenum, args[cur_arg], args[cur_arg + 1]);
4245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
4247 }
4248
4249 cur_arg += 2;
4250 }
4251 else if (!strcmp(args[cur_arg], "error-limit")) {
4252 if (!*args[cur_arg + 1]) {
4253 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4254 file, linenum, args[cur_arg]);
4255 err_code |= ERR_ALERT | ERR_FATAL;
4256 goto out;
4257 }
4258
4259 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4260
4261 if (newsrv->consecutive_errors_limit <= 0) {
4262 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4263 file, linenum, args[cur_arg]);
4264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
4266 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004267 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004268 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004269 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004270 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004271 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004272
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004274#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004275 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004276 file, linenum, "source", "usesrc");
4277#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004278 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004280#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004281 err_code |= ERR_ALERT | ERR_FATAL;
4282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 }
4284 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004285 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4286 if (!sk) {
4287 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
4290 }
4291 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004292
4293 if (port_low != port_high) {
4294 int i;
4295 if (port_low <= 0 || port_low > 65535 ||
4296 port_high <= 0 || port_high > 65535 ||
4297 port_low > port_high) {
4298 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4299 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004300 err_code |= ERR_ALERT | ERR_FATAL;
4301 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004302 }
4303 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4304 for (i = 0; i < newsrv->sport_range->size; i++)
4305 newsrv->sport_range->ports[i] = port_low + i;
4306 }
4307
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004309 while (*(args[cur_arg])) {
4310 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004311#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4312#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004313 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4314 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4315 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004318 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004319#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004320 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004321 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004322 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004325 }
4326 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004327 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004328 newsrv->state |= SRV_TPROXY_CLI;
4329 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
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_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004332 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4333 char *name, *end;
4334
4335 name = args[cur_arg+1] + 7;
4336 while (isspace(*name))
4337 name++;
4338
4339 end = name;
4340 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4341 end++;
4342
4343 newsrv->state &= ~SRV_TPROXY_MASK;
4344 newsrv->state |= SRV_TPROXY_DYN;
4345 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4346 newsrv->bind_hdr_len = end - name;
4347 memcpy(newsrv->bind_hdr_name, name, end - name);
4348 newsrv->bind_hdr_name[end-name] = '\0';
4349 newsrv->bind_hdr_occ = -1;
4350
4351 /* now look for an occurrence number */
4352 while (isspace(*end))
4353 end++;
4354 if (*end == ',') {
4355 end++;
4356 name = end;
4357 if (*end == '-')
4358 end++;
4359 while (isdigit(*end))
4360 end++;
4361 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4362 }
4363
4364 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4365 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4366 " occurrences values smaller than %d.\n",
4367 file, linenum, MAX_HDR_HISTORY);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004371 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004372 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004373 if (!sk) {
4374 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4375 err_code |= ERR_ALERT | ERR_FATAL;
4376 goto out;
4377 }
4378 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004379 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004380 }
4381 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004382#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004384#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004385 cur_arg += 2;
4386 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004387#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004388 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004389 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004392#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4393 } /* "usesrc" */
4394
4395 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4396#ifdef SO_BINDTODEVICE
4397 if (!*args[cur_arg + 1]) {
4398 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004402 }
4403 if (newsrv->iface_name)
4404 free(newsrv->iface_name);
4405
4406 newsrv->iface_name = strdup(args[cur_arg + 1]);
4407 newsrv->iface_len = strlen(newsrv->iface_name);
4408 global.last_checks |= LSTCHK_NETADM;
4409#else
4410 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4411 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_FATAL;
4413 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004414#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004415 cur_arg += 2;
4416 continue;
4417 }
4418 /* this keyword in not an option of "source" */
4419 break;
4420 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004422 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004423 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4424 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_ALERT | ERR_FATAL;
4426 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004428 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004429 if (!defsrv)
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004430 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 +01004431 file, linenum, newsrv->id);
4432 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004433 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 +01004434 file, linenum);
4435
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 }
4439 }
4440
4441 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004442 if (newsrv->trackit) {
4443 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4444 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004447 }
4448
David du Colombier6f5ccb12011-03-10 22:26:24 +01004449 switch (newsrv->check_addr.ss_family) {
4450 case AF_INET:
4451 if (!newsrv->check_port && ((struct sockaddr_in *)&newsrv->check_addr)->sin_port)
4452 newsrv->check_port = ntohs(((struct sockaddr_in *)&newsrv->check_addr)->sin_port);
4453 break;
4454 case AF_INET6:
4455 if (!newsrv->check_port && ((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port)
4456 newsrv->check_port = ntohs(((struct sockaddr_in6 *)&newsrv->check_addr)->sin6_port);
4457 break;
4458 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004459
Willy Tarreaubaaee002006-06-26 02:48:02 +02004460 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4461 newsrv->check_port = realport; /* by default */
4462 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004463 /* not yet valid, because no port was set on
4464 * the server either. We'll check if we have
4465 * a known port on the first listener.
4466 */
4467 struct listener *l;
4468 l = curproxy->listen;
4469 if (l) {
4470 int port;
4471 port = (l->addr.ss_family == AF_INET6)
4472 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
4473 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
4474 newsrv->check_port = port;
4475 }
4476 }
4477 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4479 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004483
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004484 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004485 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004486 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4487 err_code |= ERR_ALERT | ERR_ABORT;
4488 goto out;
4489 }
4490
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004491 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 newsrv->state |= SRV_CHECKED;
4493 }
4494
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004495 if (!defsrv) {
4496 if (newsrv->state & SRV_BACKUP)
4497 curproxy->srv_bck++;
4498 else
4499 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004500
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004501 newsrv->prev_state = newsrv->state;
4502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 }
4504 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01004505 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 int facility;
4507
4508 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
4509 curproxy->logfac1 = global.logfac1;
4510 curproxy->logsrv1 = global.logsrv1;
4511 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004512 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 curproxy->logfac2 = global.logfac2;
4514 curproxy->logsrv2 = global.logsrv2;
4515 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004516 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004517 }
4518 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004519 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520
4521 facility = get_log_facility(args[2]);
4522 if (facility < 0) {
4523 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
4524 exit(1);
4525 }
4526
4527 level = 7; /* max syslog level = debug */
4528 if (*(args[3])) {
4529 level = get_log_level(args[3]);
4530 if (level < 0) {
4531 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
4532 exit(1);
4533 }
4534 }
4535
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004536 minlvl = 0; /* limit syslog level to this level (emerg) */
4537 if (*(args[4])) {
4538 minlvl = get_log_level(args[4]);
4539 if (level < 0) {
4540 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
4541 exit(1);
4542 }
4543 }
4544
Robert Tsai81ae1952007-12-05 10:47:29 +01004545 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004546 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004547 if (!sk) {
4548 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004549 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
4552 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004553 logsrv.addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004554 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004555 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004556 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004557 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
4560 }
David du Colombier11bcb6c2011-03-24 12:23:00 +01004561 logsrv.addr = *sk;
4562 if (!get_host_port(&logsrv.addr))
4563 set_host_port(&logsrv.addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01004564 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565
4566 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004567 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 curproxy->logfac1 = facility;
4569 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004570 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 }
4572 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01004573 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 curproxy->logfac2 = facility;
4575 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004576 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004577 }
4578 else {
4579 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
4583 }
4584 else {
4585 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4586 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 if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004592 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004593 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004594
Willy Tarreau977b8e42006-12-29 14:19:17 +01004595 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004597
Willy Tarreaubaaee002006-06-26 02:48:02 +02004598 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004599 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4600 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004601 err_code |= ERR_ALERT | ERR_FATAL;
4602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004604
4605 /* we must first clear any optional default setting */
4606 curproxy->options &= ~PR_O_TPXY_MASK;
4607 free(curproxy->iface_name);
4608 curproxy->iface_name = NULL;
4609 curproxy->iface_len = 0;
4610
Willy Tarreaud5191e72010-02-09 20:50:45 +01004611 sk = str2sa(args[1]);
4612 if (!sk) {
4613 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
4617 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004618 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004619
4620 cur_arg = 2;
4621 while (*(args[cur_arg])) {
4622 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004623#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4624#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004625 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4626 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4627 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004630 }
4631#endif
4632 if (!*args[cur_arg + 1]) {
4633 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\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
4639 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004640 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004641 curproxy->options |= PR_O_TPXY_CLI;
4642 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004643 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004644 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004645 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4646 char *name, *end;
4647
4648 name = args[cur_arg+1] + 7;
4649 while (isspace(*name))
4650 name++;
4651
4652 end = name;
4653 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4654 end++;
4655
4656 curproxy->options &= ~PR_O_TPXY_MASK;
4657 curproxy->options |= PR_O_TPXY_DYN;
4658 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4659 curproxy->bind_hdr_len = end - name;
4660 memcpy(curproxy->bind_hdr_name, name, end - name);
4661 curproxy->bind_hdr_name[end-name] = '\0';
4662 curproxy->bind_hdr_occ = -1;
4663
4664 /* now look for an occurrence number */
4665 while (isspace(*end))
4666 end++;
4667 if (*end == ',') {
4668 end++;
4669 name = end;
4670 if (*end == '-')
4671 end++;
4672 while (isdigit(*end))
4673 end++;
4674 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4675 }
4676
4677 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4678 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4679 " occurrences values smaller than %d.\n",
4680 file, linenum, MAX_HDR_HISTORY);
4681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
4683 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004684 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004685 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004686 if (!sk) {
4687 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690 }
4691 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004692 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004693 }
4694 global.last_checks |= LSTCHK_NETADM;
4695#if !defined(CONFIG_HAP_LINUX_TPROXY)
4696 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004697#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004698#else /* no TPROXY support */
4699 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004700 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004701 err_code |= ERR_ALERT | ERR_FATAL;
4702 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004703#endif
4704 cur_arg += 2;
4705 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004706 }
4707
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004708 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4709#ifdef SO_BINDTODEVICE
4710 if (!*args[cur_arg + 1]) {
4711 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4712 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004713 err_code |= ERR_ALERT | ERR_FATAL;
4714 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004715 }
4716 if (curproxy->iface_name)
4717 free(curproxy->iface_name);
4718
4719 curproxy->iface_name = strdup(args[cur_arg + 1]);
4720 curproxy->iface_len = strlen(curproxy->iface_name);
4721 global.last_checks |= LSTCHK_NETADM;
4722#else
4723 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4724 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004727#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004728 cur_arg += 2;
4729 continue;
4730 }
4731 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4732 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004733 err_code |= ERR_ALERT | ERR_FATAL;
4734 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004737 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4738 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4739 file, linenum, "usesrc", "source");
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 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004744 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004745 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4746 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004750
4751 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4752 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004753 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004754 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004756 }
4757 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004758 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4759 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004760 args[0], args[1], NULL, (const char **)args+2);
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], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004765 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4766 ACL_DIR_REQ, ACT_DENY, 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], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4773 ACL_DIR_REQ, ACT_PASS, 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], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4780 ACL_DIR_REQ, ACT_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004785 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02004791 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004792 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4794 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004795 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004797 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004798 }
4799 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4801 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004807 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004808 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4809 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004813
4814 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4815 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004816 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004817 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 }
4820 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4822 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004823 args[0], args[1], NULL, (const char **)args+2);
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], "reqideny")) { /* deny a request if a header matches this 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_DENY, 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], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4836 ACL_DIR_REQ, ACT_PASS, 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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4843 ACL_DIR_REQ, ACT_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004848 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02004854 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004856 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004857
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 if (curproxy == &defproxy) {
4859 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004863 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004864 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 if (*(args[1]) == 0) {
4867 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004871
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004872 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4873 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4874 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4875 file, linenum, args[0]);
4876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4880 }
4881 else if (*args[2]) {
4882 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4883 file, linenum, args[0], args[2]);
4884 err_code |= ERR_ALERT | ERR_FATAL;
4885 goto out;
4886 }
4887
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004888 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004889 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004890 wl->s = strdup(args[1]);
4891 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004892 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 }
4894 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004895 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4897 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004901
Willy Tarreauade5ec42010-01-28 19:33:49 +01004902 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4903 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004904 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
4908 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004909 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4910 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004911 args[0], args[1], NULL, (const char **)args+2);
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], "rspdeny")) { /* block 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_DENY, 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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004923 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004924 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
4929
Willy Tarreauade5ec42010-01-28 19:33:49 +01004930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4931 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004932 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004935 }
4936 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4938 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004939 args[0], args[1], NULL, (const char **)args+2);
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], "rspideny")) { /* block 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_DENY, 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], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004951 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004952
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 if (curproxy == &defproxy) {
4954 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004957 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004958 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004959 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961 if (*(args[1]) == 0) {
4962 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004967 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4968 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4969 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4970 file, linenum, args[0]);
4971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
4973 }
4974 err_code |= warnif_cond_requires_req(cond, file, linenum);
4975 }
4976 else if (*args[2]) {
4977 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4978 file, linenum, args[0], args[2]);
4979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
4981 }
4982
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004983 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004984 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004985 wl->s = strdup(args[1]);
4986 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 }
4988 else if (!strcmp(args[0], "errorloc") ||
4989 !strcmp(args[0], "errorloc302") ||
4990 !strcmp(args[0], "errorloc303")) { /* error location */
4991 int errnum, errlen;
4992 char *err;
4993
Willy Tarreau977b8e42006-12-29 14:19:17 +01004994 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004996
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004998 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005001 }
5002
5003 errnum = atol(args[1]);
5004 if (!strcmp(args[0], "errorloc303")) {
5005 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5006 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5007 } else {
5008 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5009 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5010 }
5011
Willy Tarreau0f772532006-12-23 20:51:41 +01005012 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5013 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005014 chunk_destroy(&curproxy->errmsg[rc]);
5015 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005016 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005019
5020 if (rc >= HTTP_ERR_SIZE) {
5021 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5022 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 free(err);
5024 }
5025 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005026 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5027 int errnum, errlen, fd;
5028 char *err;
5029 struct stat stat;
5030
5031 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005033
5034 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005035 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005038 }
5039
5040 fd = open(args[2], O_RDONLY);
5041 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5042 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5043 file, linenum, args[2], args[1]);
5044 if (fd >= 0)
5045 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005048 }
5049
Willy Tarreau27a674e2009-08-17 07:23:33 +02005050 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005051 errlen = stat.st_size;
5052 } else {
5053 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005054 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005055 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005056 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005057 }
5058
5059 err = malloc(errlen); /* malloc() must succeed during parsing */
5060 errnum = read(fd, err, errlen);
5061 if (errnum != errlen) {
5062 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5063 file, linenum, args[2], args[1]);
5064 close(fd);
5065 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_ALERT | ERR_FATAL;
5067 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005068 }
5069 close(fd);
5070
5071 errnum = atol(args[1]);
5072 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5073 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005074 chunk_destroy(&curproxy->errmsg[rc]);
5075 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005076 break;
5077 }
5078 }
5079
5080 if (rc >= HTTP_ERR_SIZE) {
5081 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5082 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005084 free(err);
5085 }
5086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005087 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005088 struct cfg_kw_list *kwl;
5089 int index;
5090
5091 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5092 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5093 if (kwl->kw[index].section != CFG_LISTEN)
5094 continue;
5095 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5096 /* prepare error message just in case */
5097 snprintf(trash, sizeof(trash),
5098 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005099 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5100 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005101 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005104 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005105 else if (rc > 0) {
5106 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_WARN;
5108 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005109 }
Willy Tarreau93893792009-07-23 13:19:11 +02005110 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005111 }
5112 }
5113 }
5114
Willy Tarreau6daf3432008-01-22 16:44:08 +01005115 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
Willy Tarreau93893792009-07-23 13:19:11 +02005119 out:
5120 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121}
5122
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005123int
5124cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5125{
5126
5127 int err_code = 0;
5128 const char *err;
5129
5130 if (!strcmp(args[0], "userlist")) { /* new userlist */
5131 struct userlist *newul;
5132
5133 if (!*args[1]) {
5134 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5135 file, linenum, args[0]);
5136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
5138 }
5139
5140 err = invalid_char(args[1]);
5141 if (err) {
5142 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5143 file, linenum, *err, args[0], args[1]);
5144 err_code |= ERR_ALERT | ERR_FATAL;
5145 goto out;
5146 }
5147
5148 for (newul = userlist; newul; newul = newul->next)
5149 if (!strcmp(newul->name, args[1])) {
5150 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5151 file, linenum, args[1]);
5152 err_code |= ERR_WARN;
5153 goto out;
5154 }
5155
5156 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5157 if (!newul) {
5158 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5159 err_code |= ERR_ALERT | ERR_ABORT;
5160 goto out;
5161 }
5162
5163 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5164 newul->name = strdup(args[1]);
5165
5166 if (!newul->groupusers | !newul->name) {
5167 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5168 err_code |= ERR_ALERT | ERR_ABORT;
5169 goto out;
5170 }
5171
5172 newul->next = userlist;
5173 userlist = newul;
5174
5175 } else if (!strcmp(args[0], "group")) { /* new group */
5176 int cur_arg, i;
5177 const char *err;
5178
5179 if (!*args[1]) {
5180 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5181 file, linenum, args[0]);
5182 err_code |= ERR_ALERT | ERR_FATAL;
5183 goto out;
5184 }
5185
5186 err = invalid_char(args[1]);
5187 if (err) {
5188 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5189 file, linenum, *err, args[0], args[1]);
5190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
5192 }
5193
5194 for(i = 0; i < userlist->grpcnt; i++)
5195 if (!strcmp(userlist->groups[i], args[1])) {
5196 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5197 file, linenum, args[1], userlist->name);
5198 err_code |= ERR_ALERT;
5199 goto out;
5200 }
5201
5202 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5203 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5204 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5205 err_code |= ERR_ALERT | ERR_FATAL;
5206 goto out;
5207 }
5208
5209 cur_arg = 2;
5210
5211 while (*args[cur_arg]) {
5212 if (!strcmp(args[cur_arg], "users")) {
5213 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5214 cur_arg += 2;
5215 continue;
5216 } else {
5217 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5218 file, linenum, args[0]);
5219 err_code |= ERR_ALERT | ERR_FATAL;
5220 goto out;
5221 }
5222 }
5223
5224 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5225 } else if (!strcmp(args[0], "user")) { /* new user */
5226 struct auth_users *newuser;
5227 int cur_arg;
5228
5229 if (!*args[1]) {
5230 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5231 file, linenum, args[0]);
5232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
5234 }
5235
5236 for (newuser = userlist->users; newuser; newuser = newuser->next)
5237 if (!strcmp(newuser->user, args[1])) {
5238 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5239 file, linenum, args[1], userlist->name);
5240 err_code |= ERR_ALERT;
5241 goto out;
5242 }
5243
5244 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5245 if (!newuser) {
5246 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5247 err_code |= ERR_ALERT | ERR_ABORT;
5248 goto out;
5249 }
5250
5251 newuser->user = strdup(args[1]);
5252
5253 newuser->next = userlist->users;
5254 userlist->users = newuser;
5255
5256 cur_arg = 2;
5257
5258 while (*args[cur_arg]) {
5259 if (!strcmp(args[cur_arg], "password")) {
5260#ifndef CONFIG_HAP_CRYPT
5261 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5262 file, linenum);
5263 err_code |= ERR_ALERT;
5264#endif
5265 newuser->pass = strdup(args[cur_arg + 1]);
5266 cur_arg += 2;
5267 continue;
5268 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5269 newuser->pass = strdup(args[cur_arg + 1]);
5270 newuser->flags |= AU_O_INSECURE;
5271 cur_arg += 2;
5272 continue;
5273 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005274 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005275 cur_arg += 2;
5276 continue;
5277 } else {
5278 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5279 file, linenum, args[0]);
5280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
5283 }
5284 } else {
5285 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 }
5288
5289out:
5290 return err_code;
5291}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292
5293/*
5294 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005295 * Returns the error code, 0 if OK, or any combination of :
5296 * - ERR_ABORT: must abort ASAP
5297 * - ERR_FATAL: we can continue parsing but not start the service
5298 * - ERR_WARN: a warning has been emitted
5299 * - ERR_ALERT: an alert has been emitted
5300 * Only the two first ones can stop processing, the two others are just
5301 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005303int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005305 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 FILE *f;
5307 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005309 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005310
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 if ((f=fopen(file,"r")) == NULL)
5312 return -1;
5313
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005314 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005315 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005316 char *end;
5317 char *args[MAX_LINE_ARGS + 1];
5318 char *line = thisline;
5319
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 linenum++;
5321
5322 end = line + strlen(line);
5323
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005324 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5325 /* Check if we reached the limit and the last char is not \n.
5326 * Watch out for the last line without the terminating '\n'!
5327 */
5328 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005329 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005330 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005331 }
5332
Willy Tarreaubaaee002006-06-26 02:48:02 +02005333 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005334 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 line++;
5336
5337 arg = 0;
5338 args[arg] = line;
5339
5340 while (*line && arg < MAX_LINE_ARGS) {
5341 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5342 * C equivalent value. Other combinations left unchanged (eg: \1).
5343 */
5344 if (*line == '\\') {
5345 int skip = 0;
5346 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5347 *line = line[1];
5348 skip = 1;
5349 }
5350 else if (line[1] == 'r') {
5351 *line = '\r';
5352 skip = 1;
5353 }
5354 else if (line[1] == 'n') {
5355 *line = '\n';
5356 skip = 1;
5357 }
5358 else if (line[1] == 't') {
5359 *line = '\t';
5360 skip = 1;
5361 }
5362 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005363 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 unsigned char hex1, hex2;
5365 hex1 = toupper(line[2]) - '0';
5366 hex2 = toupper(line[3]) - '0';
5367 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5368 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5369 *line = (hex1<<4) + hex2;
5370 skip = 3;
5371 }
5372 else {
5373 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 }
5376 }
5377 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005378 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 end -= skip;
5380 }
5381 line++;
5382 }
5383 else if (*line == '#' || *line == '\n' || *line == '\r') {
5384 /* end of string, end of loop */
5385 *line = 0;
5386 break;
5387 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005388 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005390 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005391 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392 line++;
5393 args[++arg] = line;
5394 }
5395 else {
5396 line++;
5397 }
5398 }
5399
5400 /* empty line */
5401 if (!**args)
5402 continue;
5403
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005404 if (*line) {
5405 /* we had to stop due to too many args.
5406 * Let's terminate the string, print the offending part then cut the
5407 * last arg.
5408 */
5409 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5410 line++;
5411 *line = '\0';
5412
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005413 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005414 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005415 err_code |= ERR_ALERT | ERR_FATAL;
5416 args[arg] = line;
5417 }
5418
Willy Tarreau540abe42007-05-02 20:50:16 +02005419 /* zero out remaining args and ensure that at least one entry
5420 * is zeroed out.
5421 */
5422 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005423 args[arg] = line;
5424 }
5425
Willy Tarreau3842f002009-06-14 11:39:52 +02005426 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005427 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005428 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005429 for (arg=0; *args[arg+1]; arg++)
5430 args[arg] = args[arg+1]; // shift args after inversion
5431 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005432 else if (!strcmp(args[0], "default")) {
5433 kwm = KWM_DEF;
5434 for (arg=0; *args[arg+1]; arg++)
5435 args[arg] = args[arg+1]; // shift args after inversion
5436 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005437
Willy Tarreau3842f002009-06-14 11:39:52 +02005438 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
5439 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005440 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005441 }
5442
Willy Tarreau977b8e42006-12-29 14:19:17 +01005443 if (!strcmp(args[0], "listen") ||
5444 !strcmp(args[0], "frontend") ||
5445 !strcmp(args[0], "backend") ||
5446 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005447 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005448 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005449 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005450 cursection = strdup(args[0]);
5451 }
5452 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005454 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005455 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005456 }
5457 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005458 confsect = CFG_USERLIST;
5459 free(cursection);
5460 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005461 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005462 else if (!strcmp(args[0], "peers")) {
5463 confsect = CFG_PEERS;
5464 free(cursection);
5465 cursection = strdup(args[0]);
5466 }
5467
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 /* else it's a section keyword */
5469
5470 switch (confsect) {
5471 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005472 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 break;
5474 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005475 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005477 case CFG_USERLIST:
5478 err_code |= cfg_parse_users(file, linenum, args, kwm);
5479 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005480 case CFG_PEERS:
5481 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5482 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005484 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005485 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005487
5488 if (err_code & ERR_ABORT)
5489 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005491 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005492 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005494 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005495}
5496
Willy Tarreaubb925012009-07-23 13:36:36 +02005497/*
5498 * Returns the error code, 0 if OK, or any combination of :
5499 * - ERR_ABORT: must abort ASAP
5500 * - ERR_FATAL: we can continue parsing but not start the service
5501 * - ERR_WARN: a warning has been emitted
5502 * - ERR_ALERT: an alert has been emitted
5503 * Only the two first ones can stop processing, the two others are just
5504 * indicators.
5505 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005506int check_config_validity()
5507{
5508 int cfgerr = 0;
5509 struct proxy *curproxy = NULL;
5510 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005511 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005512 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005513 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514
5515 /*
5516 * Now, check for the integrity of all that we have collected.
5517 */
5518
5519 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005520 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005521
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005522 /* first, we will invert the proxy list order */
5523 curproxy = NULL;
5524 while (proxy) {
5525 struct proxy *next;
5526
5527 next = proxy->next;
5528 proxy->next = curproxy;
5529 curproxy = proxy;
5530 if (!next)
5531 break;
5532 proxy = next;
5533 }
5534
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005536 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02005537 err_code |= ERR_ALERT | ERR_FATAL;
5538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 }
5540
5541 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005542 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005543 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005544 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005545 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005546 unsigned int next_id;
5547
5548 if (!curproxy->uuid) {
5549 /* proxy ID not set, use automatic numbering with first
5550 * spare entry starting with next_pxid.
5551 */
5552 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5553 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5554 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005555 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005556 next_pxid++;
5557
Willy Tarreau55ea7572007-06-17 19:56:27 +02005558
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005560 /* ensure we don't keep listeners uselessly bound */
5561 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 curproxy = curproxy->next;
5563 continue;
5564 }
5565
Willy Tarreauff01a212009-03-15 13:46:16 +01005566 switch (curproxy->mode) {
5567 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005568 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005569 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005570 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5571 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005572 cfgerr++;
5573 }
5574
5575 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005576 Warning("config : servers will be ignored for %s '%s'.\n",
5577 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005578 break;
5579
5580 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005581 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005582 break;
5583
5584 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005585 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005586 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005587 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
5588 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005589 cfgerr++;
5590 }
5591 break;
5592 }
5593
5594 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005595 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5596 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 cfgerr++;
5598 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005599
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005600 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005601 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005602 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005603 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5604 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005605 cfgerr++;
5606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005608 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005609 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5610 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005611 cfgerr++;
5612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613#endif
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005614 else if (curproxy->options2 & PR_O2_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005615 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5616 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005617 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005618 }
5619 }
5620 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
Willy Tarreauf5ab69a2011-03-04 22:44:16 +01005621 !(curproxy->options2 & PR_O2_DISPATCH)) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005622 /* If no LB algo is set in a backend, and we're not in
5623 * transparent mode, dispatch mode nor proxy mode, we
5624 * want to use balance roundrobin by default.
5625 */
5626 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5627 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 }
5629 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005630
Willy Tarreaud6cc5322011-03-04 17:30:54 +01005631 if (curproxy->options2 & PR_O2_DISPATCH) {
5632 curproxy->options &= ~PR_O_TRANSP;
5633 curproxy->options &= ~PR_O_HTTP_PROXY;
5634 }
5635 else if (curproxy->options & PR_O_HTTP_PROXY) {
5636 curproxy->options2 &= ~PR_O2_DISPATCH;
5637 curproxy->options &= ~PR_O_TRANSP;
5638 }
5639 else if (curproxy->options & PR_O_TRANSP) {
5640 curproxy->options2 &= ~PR_O2_DISPATCH;
5641 curproxy->options &= ~PR_O_HTTP_PROXY;
5642 }
5643
Willy Tarreau82936582007-11-30 15:20:09 +01005644 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
5645 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005646 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5647 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005648 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01005649 }
5650
Willy Tarreauef781042010-01-27 11:53:01 +01005651 if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
5652 curproxy->options &= ~PR_O2_CHK_SNDST;
5653 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5654 "send-state", proxy_type_str(curproxy), curproxy->id);
5655 err_code |= ERR_WARN;
5656 }
5657
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005658 /* if a default backend was specified, let's find it */
5659 if (curproxy->defbe.name) {
5660 struct proxy *target;
5661
Alex Williams96532db2009-11-01 21:27:13 -05005662 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005663 if (!target) {
5664 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5665 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005666 cfgerr++;
5667 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005668 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5669 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005670 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005671 } else {
5672 free(curproxy->defbe.name);
5673 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005674 /* we force the backend to be present on at least all of
5675 * the frontend's processes.
5676 */
5677 target->bind_proc = curproxy->bind_proc ?
5678 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 }
5680 }
5681
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005682 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005683 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5684 /* map jump target for ACT_SETBE in req_rep chain */
5685 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005686 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005687 struct proxy *target;
5688
Willy Tarreaua496b602006-12-17 23:15:24 +01005689 if (exp->action != ACT_SETBE)
5690 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005691
Alex Williams96532db2009-11-01 21:27:13 -05005692 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005693 if (!target) {
5694 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5695 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005696 cfgerr++;
5697 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005698 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5699 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005700 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005701 } else {
5702 free((void *)exp->replace);
5703 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005704 /* we force the backend to be present on at least all of
5705 * the frontend's processes.
5706 */
5707 target->bind_proc = curproxy->bind_proc ?
5708 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005709 }
5710 }
5711 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005712
5713 /* find the target proxy for 'use_backend' rules */
5714 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005715 struct proxy *target;
5716
Alex Williams96532db2009-11-01 21:27:13 -05005717 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005718
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005719 if (!target) {
5720 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5721 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005722 cfgerr++;
5723 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005724 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5725 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005726 cfgerr++;
5727 } else {
5728 free((void *)rule->be.name);
5729 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005730 /* we force the backend to be present on at least all of
5731 * the frontend's processes.
5732 */
5733 target->bind_proc = curproxy->bind_proc ?
5734 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005735 }
5736 }
5737
Emeric Brunb982a3d2010-01-04 15:45:53 +01005738 /* find the target table for 'stick' rules */
5739 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5740 struct proxy *target;
5741
Emeric Brun1d33b292010-01-04 15:47:17 +01005742 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5743 if (mrule->flags & STK_IS_STORE)
5744 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5745
Emeric Brunb982a3d2010-01-04 15:45:53 +01005746 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005747 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005748 else
5749 target = curproxy;
5750
5751 if (!target) {
5752 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5753 curproxy->id, mrule->table.name);
5754 cfgerr++;
5755 }
5756 else if (target->table.size == 0) {
5757 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5758 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5759 cfgerr++;
5760 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005761 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005762 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5763 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5764 cfgerr++;
5765 }
5766 else {
5767 free((void *)mrule->table.name);
5768 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005769 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005770 }
5771 }
5772
5773 /* find the target table for 'store response' rules */
5774 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5775 struct proxy *target;
5776
Emeric Brun1d33b292010-01-04 15:47:17 +01005777 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5778
Emeric Brunb982a3d2010-01-04 15:45:53 +01005779 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005780 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005781 else
5782 target = curproxy;
5783
5784 if (!target) {
5785 Alert("Proxy '%s': unable to find store table '%s'.\n",
5786 curproxy->id, mrule->table.name);
5787 cfgerr++;
5788 }
5789 else if (target->table.size == 0) {
5790 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5791 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5792 cfgerr++;
5793 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005794 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005795 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5796 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5797 cfgerr++;
5798 }
5799 else {
5800 free((void *)mrule->table.name);
5801 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005802 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005803 }
5804 }
5805
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005806 /* find the target table for 'tcp-request' layer 4 rules */
5807 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5808 struct proxy *target;
5809
Willy Tarreau56123282010-08-06 19:06:56 +02005810 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005811 continue;
5812
5813 if (trule->act_prm.trk_ctr.table.n)
5814 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5815 else
5816 target = curproxy;
5817
5818 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005819 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5820 curproxy->id, trule->act_prm.trk_ctr.table.n,
5821 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005822 cfgerr++;
5823 }
5824 else if (target->table.size == 0) {
5825 Alert("Proxy '%s': table '%s' used but not configured.\n",
5826 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5827 cfgerr++;
5828 }
5829 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005830 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 +02005831 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5832 cfgerr++;
5833 }
5834 else {
5835 free(trule->act_prm.trk_ctr.table.n);
5836 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005837 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005838 * to pass a list of counters to track and allocate them right here using
5839 * stktable_alloc_data_type().
5840 */
5841 }
5842 }
5843
Willy Tarreaud1f96522010-08-03 19:34:32 +02005844 /* find the target table for 'tcp-request' layer 6 rules */
5845 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5846 struct proxy *target;
5847
Willy Tarreau56123282010-08-06 19:06:56 +02005848 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005849 continue;
5850
5851 if (trule->act_prm.trk_ctr.table.n)
5852 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5853 else
5854 target = curproxy;
5855
5856 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005857 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5858 curproxy->id, trule->act_prm.trk_ctr.table.n,
5859 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005860 cfgerr++;
5861 }
5862 else if (target->table.size == 0) {
5863 Alert("Proxy '%s': table '%s' used but not configured.\n",
5864 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5865 cfgerr++;
5866 }
5867 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005868 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 +02005869 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5870 cfgerr++;
5871 }
5872 else {
5873 free(trule->act_prm.trk_ctr.table.n);
5874 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005875 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005876 * to pass a list of counters to track and allocate them right here using
5877 * stktable_alloc_data_type().
5878 */
5879 }
5880 }
5881
Emeric Brun32da3c42010-09-23 18:39:19 +02005882 if (curproxy->table.peers.name) {
5883 struct peers *curpeers = peers;
5884
5885 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5886 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5887 free((void *)curproxy->table.peers.name);
5888 curproxy->table.peers.p = peers;
5889 break;
5890 }
5891 }
5892
5893 if (!curpeers) {
5894 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5895 curproxy->id, curproxy->table.peers.name);
5896 cfgerr++;
5897 }
5898 else if (!curpeers->peers_fe) {
5899 Alert("Proxy '%s': unable to identify local peer in peers section '%s'.\n",
5900 curproxy->id, curpeers->id);
5901 cfgerr++;
5902 }
5903 }
5904
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005905 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005906 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005907 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5908 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5909 "proxy", curproxy->id);
5910 cfgerr++;
5911 goto out_uri_auth_compat;
5912 }
5913
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005914 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005915 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005916 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005917 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005918
Willy Tarreau95fa4692010-02-01 13:05:50 +01005919 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5920 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005921
5922 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005923 uri_auth_compat_req[i++] = "realm";
5924 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5925 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005926
Willy Tarreau95fa4692010-02-01 13:05:50 +01005927 uri_auth_compat_req[i++] = "unless";
5928 uri_auth_compat_req[i++] = "{";
5929 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5930 uri_auth_compat_req[i++] = "}";
5931 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005932
Willy Tarreauff011f22011-01-06 17:51:27 +01005933 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5934 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005935 cfgerr++;
5936 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005937 }
5938
Willy Tarreauff011f22011-01-06 17:51:27 +01005939 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01005940
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005941 if (curproxy->uri_auth->auth_realm) {
5942 free(curproxy->uri_auth->auth_realm);
5943 curproxy->uri_auth->auth_realm = NULL;
5944 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005945
5946 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005947 }
5948out_uri_auth_compat:
5949
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01005950 cfgerr += acl_find_targets(curproxy);
5951
Willy Tarreau2738a142006-07-08 17:28:09 +02005952 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005953 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02005954 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005955 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005956 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02005957 " | While not properly invalid, you will certainly encounter various problems\n"
5958 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01005959 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005960 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005961 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02005962 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02005963
Willy Tarreau1fa31262007-12-03 00:36:16 +01005964 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
5965 * We must still support older configurations, so let's find out whether those
5966 * parameters have been set or must be copied from contimeouts.
5967 */
5968 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005969 if (!curproxy->timeout.tarpit ||
5970 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005971 /* tarpit timeout not set. We search in the following order:
5972 * default.tarpit, curr.connect, default.connect.
5973 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005974 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005975 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005976 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005977 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005978 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005979 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005980 }
5981 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005982 (!curproxy->timeout.queue ||
5983 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01005984 /* queue timeout not set. We search in the following order:
5985 * default.queue, curr.connect, default.connect.
5986 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005987 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01005988 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005989 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005990 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02005991 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005992 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01005993 }
5994 }
5995
Willy Tarreau07a54902010-03-29 18:33:29 +02005996 if (curproxy->options2 & PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01005997 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
5998 curproxy->check_req = (char *)malloc(curproxy->check_len);
5999 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006000 }
6001
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006002 /* The small pools required for the capture lists */
6003 if (curproxy->nb_req_cap)
6004 curproxy->req_cap_pool = create_pool("ptrcap",
6005 curproxy->nb_req_cap * sizeof(char *),
6006 MEM_F_SHARED);
6007 if (curproxy->nb_rsp_cap)
6008 curproxy->rsp_cap_pool = create_pool("ptrcap",
6009 curproxy->nb_rsp_cap * sizeof(char *),
6010 MEM_F_SHARED);
6011
Willy Tarreau1d4154a2007-05-13 22:57:02 +02006012 curproxy->hdr_idx_pool = create_pool("hdr_idx",
6013 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
6014 MEM_F_SHARED);
6015
Willy Tarreau86034312006-12-29 00:10:33 +01006016 /* for backwards compatibility with "listen" instances, if
6017 * fullconn is not set but maxconn is set, then maxconn
6018 * is used.
6019 */
6020 if (!curproxy->fullconn)
6021 curproxy->fullconn = curproxy->maxconn;
6022
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023 /* first, we will invert the servers list order */
6024 newsrv = NULL;
6025 while (curproxy->srv) {
6026 struct server *next;
6027
6028 next = curproxy->srv->next;
6029 curproxy->srv->next = newsrv;
6030 newsrv = curproxy->srv;
6031 if (!next)
6032 break;
6033 curproxy->srv = next;
6034 }
6035
Willy Tarreaudd701652010-05-25 23:03:02 +02006036 /* assign automatic UIDs to servers which don't have one yet */
6037 next_id = 1;
6038 newsrv = curproxy->srv;
6039 while (newsrv != NULL) {
6040 if (!newsrv->puid) {
6041 /* server ID not set, use automatic numbering with first
6042 * spare entry starting with next_svid.
6043 */
6044 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6045 newsrv->conf.id.key = newsrv->puid = next_id;
6046 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6047 }
6048 next_id++;
6049 newsrv = newsrv->next;
6050 }
6051
Willy Tarreau20697042007-11-15 23:26:18 +01006052 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006053 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006055 /* We have to initialize the server lookup mechanism depending
6056 * on what LB algorithm was choosen.
6057 */
6058
6059 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6060 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6061 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006062 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6063 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6064 init_server_map(curproxy);
6065 } else {
6066 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6067 fwrr_init_server_groups(curproxy);
6068 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006069 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006070
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006071 case BE_LB_KIND_LC:
6072 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01006073 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006074 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006075
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006076 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006077 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6078 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6079 chash_init_server_tree(curproxy);
6080 } else {
6081 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6082 init_server_map(curproxy);
6083 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006084 break;
6085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006086
6087 if (curproxy->options & PR_O_LOGASAP)
6088 curproxy->to_log &= ~LW_BYTES;
6089
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006090 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
6091 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
6092 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6093 proxy_type_str(curproxy), curproxy->id);
6094 err_code |= ERR_WARN;
6095 }
6096
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006097 if (curproxy->mode != PR_MODE_HTTP) {
6098 int optnum;
6099
6100 if (curproxy->options & PR_O_COOK_ANY) {
6101 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6102 proxy_type_str(curproxy), curproxy->id);
6103 err_code |= ERR_WARN;
6104 }
6105
6106 if (curproxy->uri_auth) {
6107 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6108 proxy_type_str(curproxy), curproxy->id);
6109 err_code |= ERR_WARN;
6110 curproxy->uri_auth = NULL;
6111 }
6112
6113 if (curproxy->options & PR_O_FWDFOR) {
6114 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6115 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6116 err_code |= ERR_WARN;
6117 curproxy->options &= ~PR_O_FWDFOR;
6118 }
6119
6120 if (curproxy->options & PR_O_ORGTO) {
6121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6122 "originalto", proxy_type_str(curproxy), curproxy->id);
6123 err_code |= ERR_WARN;
6124 curproxy->options &= ~PR_O_ORGTO;
6125 }
6126
6127 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6128 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6129 (curproxy->cap & cfg_opts[optnum].cap) &&
6130 (curproxy->options & cfg_opts[optnum].val)) {
6131 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6132 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6133 err_code |= ERR_WARN;
6134 curproxy->options &= ~cfg_opts[optnum].val;
6135 }
6136 }
6137
6138 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6139 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6140 (curproxy->cap & cfg_opts2[optnum].cap) &&
6141 (curproxy->options2 & cfg_opts2[optnum].val)) {
6142 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6143 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6144 err_code |= ERR_WARN;
6145 curproxy->options2 &= ~cfg_opts2[optnum].val;
6146 }
6147 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006148
Willy Tarreauefa5f512010-03-30 20:13:29 +02006149#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006150 if (curproxy->bind_hdr_occ) {
6151 curproxy->bind_hdr_occ = 0;
6152 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6153 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6154 err_code |= ERR_WARN;
6155 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006156#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006157 }
6158
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006160 * ensure that we're not cross-dressing a TCP server into HTTP.
6161 */
6162 newsrv = curproxy->srv;
6163 while (newsrv != NULL) {
6164 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006165 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6166 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006167 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006168 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006169
Willy Tarreauefa5f512010-03-30 20:13:29 +02006170#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006171 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6172 newsrv->bind_hdr_occ = 0;
6173 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6174 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6175 err_code |= ERR_WARN;
6176 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006177#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006178 newsrv = newsrv->next;
6179 }
6180
6181 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182 * If this server supports a maxconn parameter, it needs a dedicated
6183 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006184 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006185 */
6186 newsrv = curproxy->srv;
6187 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01006188 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189 /* Only 'minconn' was specified, or it was higher than or equal
6190 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6191 * this will avoid further useless expensive computations.
6192 */
6193 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01006194 } else if (newsrv->maxconn && !newsrv->minconn) {
6195 /* minconn was not specified, so we set it to maxconn */
6196 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006197 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006198 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
6199 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006200 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 }
6202
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006203 if (newsrv->trackit) {
6204 struct proxy *px;
6205 struct server *srv;
6206 char *pname, *sname;
6207
6208 pname = newsrv->trackit;
6209 sname = strrchr(pname, '/');
6210
6211 if (sname)
6212 *sname++ = '\0';
6213 else {
6214 sname = pname;
6215 pname = NULL;
6216 }
6217
6218 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05006219 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006220 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006221 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6222 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006223 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006224 cfgerr++;
6225 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006226 }
6227 } else
6228 px = curproxy;
6229
6230 srv = findserver(px, sname);
6231 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006232 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6233 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006234 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02006235 cfgerr++;
6236 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006237 }
6238
6239 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006240 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05006241 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006242 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006243 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006244 cfgerr++;
6245 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006246 }
6247
6248 if (curproxy != px &&
6249 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006250 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Willy Tarreauef781042010-01-27 11:53:01 +01006251 "tracking: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006252 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006253 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006254 cfgerr++;
6255 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01006256 }
6257
6258 newsrv->tracked = srv;
6259 newsrv->tracknext = srv->tracknext;
6260 srv->tracknext = newsrv;
6261
6262 free(newsrv->trackit);
6263 }
Willy Tarreaubb925012009-07-23 13:36:36 +02006264 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 newsrv = newsrv->next;
6266 }
6267
Willy Tarreauc1a21672009-08-16 22:37:44 +02006268 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006269 curproxy->accept = frontend_accept;
6270
Willy Tarreauc1a21672009-08-16 22:37:44 +02006271 if (curproxy->tcp_req.inspect_delay ||
6272 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006273 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006274
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006275 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006276 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006277 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006278 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006279
6280 /* both TCP and HTTP must check switching rules */
6281 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6282 }
6283
6284 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006285 if (curproxy->tcp_req.inspect_delay ||
6286 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6287 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6288
Emeric Brun97679e72010-09-23 17:56:44 +02006289 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6290 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6291
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006292 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006293 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006294 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006295 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006296
6297 /* If the backend does requires RDP cookie persistence, we have to
6298 * enable the corresponding analyser.
6299 */
6300 if (curproxy->options2 & PR_O2_RDPC_PRST)
6301 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6302 }
6303
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006304 listener = NULL;
6305 while (curproxy->listen) {
6306 struct listener *next;
6307
6308 next = curproxy->listen->next;
6309 curproxy->listen->next = listener;
6310 listener = curproxy->listen;
6311
6312 if (!next)
6313 break;
6314
6315 curproxy->listen = next;
6316 }
6317
Willy Tarreaue6b98942007-10-29 01:09:36 +01006318 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006319 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006320 listener = curproxy->listen;
6321 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006322 if (!listener->luid) {
6323 /* listener ID not set, use automatic numbering with first
6324 * spare entry starting with next_luid.
6325 */
6326 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6327 listener->conf.id.key = listener->luid = next_id;
6328 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006329 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006330 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006331
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006332 /* enable separate counters */
6333 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6334 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6335 if (!listener->name) {
6336 sprintf(trash, "sock-%d", listener->luid);
6337 listener->name = strdup(trash);
6338 }
6339 }
6340
Willy Tarreaue6b98942007-10-29 01:09:36 +01006341 if (curproxy->options & PR_O_TCP_NOLING)
6342 listener->options |= LI_O_NOLINGER;
6343 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006344 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006345 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006346 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006347 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006348 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006349 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006350
Willy Tarreau8a956912010-10-15 14:27:08 +02006351 if (listener->options & LI_O_ACC_PROXY)
6352 listener->analysers |= AN_REQ_DECODE_PROXY;
6353
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006354 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6355 listener->options |= LI_O_TCP_RULES;
6356
Willy Tarreaude3041d2010-05-31 10:56:17 +02006357 if (curproxy->mon_mask.s_addr)
6358 listener->options |= LI_O_CHK_MONNET;
6359
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006360 /* smart accept mode is automatic in HTTP mode */
6361 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6362 (curproxy->mode == PR_MODE_HTTP &&
6363 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6364 listener->options |= LI_O_NOQUICKACK;
6365
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006366 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006367 listener = listener->next;
6368 }
6369
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006370 /* Check multi-process mode compatibility for the current proxy */
6371 if (global.nbproc > 1) {
6372 int nbproc = 0;
6373 if (curproxy->bind_proc) {
6374 int proc;
6375 for (proc = 0; proc < global.nbproc; proc++) {
6376 if (curproxy->bind_proc & (1 << proc)) {
6377 nbproc++;
6378 }
6379 }
6380 } else {
6381 nbproc = global.nbproc;
6382 }
6383 if (curproxy->table.peers.name) {
6384 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6385 curproxy->id);
6386 cfgerr++;
6387 }
6388 if (nbproc > 1) {
6389 if (curproxy->uri_auth) {
6390 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6391 curproxy->id);
6392 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6393 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6394 curproxy->id);
6395 }
6396 }
6397 if (curproxy->appsession_name) {
6398 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6399 curproxy->id);
6400 }
6401 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6402 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6403 curproxy->id);
6404 }
6405 }
6406 }
6407
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 curproxy = curproxy->next;
6409 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006410
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006411 /* Check multi-process mode compatibility */
6412 if (global.nbproc > 1) {
6413 if (global.stats_fe) {
6414 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6415 }
6416 }
6417
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006418 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6419 struct auth_users *curuser;
6420 int g;
6421
6422 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6423 unsigned int group_mask = 0;
6424 char *group = NULL;
6425
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006426 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006427 continue;
6428
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006429 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006430
6431 for (g = 0; g < curuserlist->grpcnt; g++)
6432 if (!strcmp(curuserlist->groups[g], group))
6433 break;
6434
6435 if (g == curuserlist->grpcnt) {
6436 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6437 curuserlist->name, group, curuser->user);
6438 err_code |= ERR_ALERT | ERR_FATAL;
6439 goto out;
6440 }
6441
6442 group_mask |= (1 << g);
6443 }
6444
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006445 free(curuser->u.groups);
6446 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006447 }
6448
6449 for (g = 0; g < curuserlist->grpcnt; g++) {
6450 char *user = NULL;
6451
6452 if (!curuserlist->groupusers[g])
6453 continue;
6454
6455 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6456 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6457 if (!strcmp(curuser->user, user))
6458 break;
6459
6460 if (!curuser) {
6461 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6462 curuserlist->name, user, curuserlist->groups[g]);
6463 err_code |= ERR_ALERT | ERR_FATAL;
6464 goto out;
6465 }
6466
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006467 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006468 }
6469
6470 free(curuserlist->groupusers[g]);
6471 }
6472
6473 free(curuserlist->groupusers);
6474
6475#ifdef DEBUG_AUTH
6476 for (g = 0; g < curuserlist->grpcnt; g++) {
6477 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6478
6479 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6480 if (curuser->group_mask & (1 << g))
6481 fprintf(stderr, " %s", curuser->user);
6482 }
6483
6484 fprintf(stderr, "\n");
6485 }
6486#endif
6487
6488 }
6489
Willy Tarreau056f5682010-06-06 15:51:11 +02006490 /* initialize stick-tables on backend capable proxies. This must not
6491 * be done earlier because the data size may be discovered while parsing
6492 * other proxies.
6493 */
6494 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006495 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006496
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006497 /*
6498 * Recount currently required checks.
6499 */
6500
6501 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6502 int optnum;
6503
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006504 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6505 if (curproxy->options & cfg_opts[optnum].val)
6506 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006507
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006508 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6509 if (curproxy->options2 & cfg_opts2[optnum].val)
6510 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006511 }
6512
Willy Tarreaubb925012009-07-23 13:36:36 +02006513 if (cfgerr > 0)
6514 err_code |= ERR_ALERT | ERR_FATAL;
6515 out:
6516 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006517}
6518
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006519/*
6520 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6521 * parsing sessions.
6522 */
6523void cfg_register_keywords(struct cfg_kw_list *kwl)
6524{
6525 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6526}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006528/*
6529 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6530 */
6531void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6532{
6533 LIST_DEL(&kwl->list);
6534 LIST_INIT(&kwl->list);
6535}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006536
6537/*
6538 * Local variables:
6539 * c-indent-level: 8
6540 * c-basic-offset: 8
6541 * End:
6542 */