blob: 5996e26728e8d1b0f3ba8085813a8dcd9f5cc24b [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010049#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020050#include <proto/lb_fwlc.h>
51#include <proto/lb_fwrr.h>
52#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010054#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010065#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066
67
Willy Tarreauf3c69202006-07-09 16:42:34 +020068/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
69 * ssl-hello-chk option to ensure that the remote server speaks SSL.
70 *
71 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
72 */
73const char sslv3_client_hello_pkt[] = {
74 "\x16" /* ContentType : 0x16 = Hanshake */
75 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
76 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
77 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
78 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
79 "\x03\x00" /* Hello Version : 0x0300 = v3 */
80 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
81 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
82 "\x00" /* Session ID length : empty (no session ID) */
83 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
84 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
85 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
86 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
87 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
88 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
89 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
90 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
91 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
92 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
93 "\x00\x38" "\x00\x39" "\x00\x3A"
94 "\x01" /* Compression Length : 0x01 = 1 byte for types */
95 "\x00" /* Compression Type : 0x00 = NULL compression */
96};
97
Willy Tarreau3842f002009-06-14 11:39:52 +020098/* various keyword modifiers */
99enum kw_mod {
100 KWM_STD = 0, /* normal */
101 KWM_NO, /* "no" prefixed before the keyword */
102 KWM_DEF, /* "default" prefixed before the keyword */
103};
104
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107 const char *name;
108 unsigned int val;
109 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100111 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112};
113
114/* proxy->options */
115static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
118 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
119 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
120 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
121 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
122 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
123 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
127 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
129 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
130 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
131 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
132 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100133#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100135#else
136 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100137#endif
138
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100139 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140};
141
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142/* proxy->options2 */
143static const struct cfg_opt cfg_opts2[] =
144{
145#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100146 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
148 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100149#else
150 { "splice-request", 0, 0, 0, 0 },
151 { "splice-response", 0, 0, 0, 0 },
152 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100153#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
155 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
157 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
158 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
159 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
161 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
162 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
163 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200164 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200165 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100166 { NULL, 0, 0, 0 }
167};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168
Willy Tarreau6daf3432008-01-22 16:44:08 +0100169static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
171int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100172int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200174/* List head of all known configuration keywords */
175static struct cfg_kw_list cfg_keywords = {
176 .list = LIST_HEAD_INIT(cfg_keywords.list)
177};
178
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179/*
180 * converts <str> to a list of listeners which are dynamically allocated.
181 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
182 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
183 * - <port> is a numerical port from 1 to 65535 ;
184 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
185 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100188static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189{
190 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100191 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192 int port, end;
193
194 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200195
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 while (next && *next) {
197 struct sockaddr_storage ss;
198
199 str = next;
200 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100201 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 *next++ = 0;
203 }
204
Emeric Bruned760922010-10-22 17:59:25 +0200205 if (*str == '/') {
206 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
207 /* so compute max path */
208 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
209 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 +0200210
Emeric Bruned760922010-10-22 17:59:25 +0200211 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100212 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
213 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200214 goto fail;
215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200218 ss.ss_family = AF_UNIX;
219 if (global.unix_bind.prefix) {
220 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
221 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 }
Emeric Bruned760922010-10-22 17:59:25 +0200223 else {
224 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
225 }
226 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 }
228 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100231 ss2 = str2sa_range(str, &port, &end);
232 if (!ss2) {
233 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
234 file, line, str);
235 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 if (!port) {
239 Alert("parsing [%s:%d] : missing port number: '%s'\n",
240 file, line, str);
241 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 /* OK the address looks correct */
245 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Emeric Bruned760922010-10-22 17:59:25 +0200247 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
249 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200250 goto fail;
251 }
252
253 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
255 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 }
259
260 for (; port <= end; port++) {
261 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200262 l->next = curproxy->listen;
263 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
265 l->fd = -1;
266 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 l->state = LI_INIT;
268
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100269 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100271 tcpv4_add_listener(l);
272 }
Emeric Bruned760922010-10-22 17:59:25 +0200273 else if (ss.ss_family == AF_INET6) {
274 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
275 tcpv6_add_listener(l);
276 }
277 else {
278 l->perm.ux.gid = l->perm.ux.uid = -1;
279 l->perm.ux.mode = 0;
280 uxst_add_listener(l);
281 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200282
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200283 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100284 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 } /* end for(port) */
286 } /* end while(next) */
287 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 fail:
290 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292}
293
Willy Tarreau977b8e42006-12-29 14:19:17 +0100294/*
295 * Sends a warning if proxy <proxy> does not have at least one of the
296 * capabilities in <cap>. An optionnal <hint> may be added at the end
297 * of the warning to help the user. Returns 1 if a warning was emitted
298 * or 0 if the condition is valid.
299 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100300int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301{
302 char *msg;
303
304 switch (cap) {
305 case PR_CAP_BE: msg = "no backend"; break;
306 case PR_CAP_FE: msg = "no frontend"; break;
307 case PR_CAP_RS: msg = "no ruleset"; break;
308 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
309 default: msg = "not enough"; break;
310 }
311
312 if (!(proxy->cap & cap)) {
313 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100314 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100315 return 1;
316 }
317 return 0;
318}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319
Willy Tarreau61d18892009-03-31 10:49:21 +0200320/* Report a warning if a rule is placed after a 'block' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
325 if (!LIST_ISEMPTY(&proxy->block_cond)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a reqrewrite rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
338 if (proxy->req_exp) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* Report a warning if a rule is placed after a reqadd rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100351 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a redirect rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a 'use_backend' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
389 warnif_rule_after_reqadd(proxy, file, line, arg) ||
390 warnif_rule_after_redirect(proxy, file, line, arg) ||
391 warnif_rule_after_use_backend(proxy, file, line, arg);
392}
393
394/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100409/* Report it if a request ACL condition uses some response-only parameters. It
410 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
421 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100426/* Report it if a request ACL condition uses some request-only volatile parameters.
427 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
428 * Note that <cond> may be NULL and then will be ignored.
429 */
430static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
431{
432 struct acl *acl;
433
434 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
435 return 0;
436
437 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
438 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
439 file, line, acl ? acl->name : "(unknown)");
440 return ERR_WARN;
441}
442
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100443
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 * parse a line in a <global> section. Returns the error code, 0 if OK, or
446 * any combination of :
447 * - ERR_ABORT: must abort ASAP
448 * - ERR_FATAL: we can continue parsing but not start the service
449 * - ERR_WARN: a warning has been emitted
450 * - ERR_ALERT: an alert has been emitted
451 * Only the two first ones can stop processing, the two others are just
452 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200454int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455{
Willy Tarreau058e9072009-07-20 09:30:05 +0200456 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457
458 if (!strcmp(args[0], "global")) { /* new section */
459 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 }
462 else if (!strcmp(args[0], "daemon")) {
463 global.mode |= MODE_DAEMON;
464 }
465 else if (!strcmp(args[0], "debug")) {
466 global.mode |= MODE_DEBUG;
467 }
468 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100469 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100472 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200473 }
474 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100480 else if (!strcmp(args[0], "nosplice")) {
481 global.tune.options &= ~GTUNE_USE_SPLICE;
482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 else if (!strcmp(args[0], "quiet")) {
484 global.mode |= MODE_QUIET;
485 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200486 else if (!strcmp(args[0], "tune.maxpollevents")) {
487 if (global.tune.maxpollevents != 0) {
488 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT;
490 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200491 }
492 if (*(args[1]) == 0) {
493 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT | ERR_FATAL;
495 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200496 }
497 global.tune.maxpollevents = atol(args[1]);
498 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100499 else if (!strcmp(args[0], "tune.maxaccept")) {
500 if (global.tune.maxaccept != 0) {
501 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200502 err_code |= ERR_ALERT;
503 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100504 }
505 if (*(args[1]) == 0) {
506 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT | ERR_FATAL;
508 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100509 }
510 global.tune.maxaccept = atol(args[1]);
511 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200512 else if (!strcmp(args[0], "tune.chksize")) {
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517 }
518 global.tune.chksize = atol(args[1]);
519 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200520 else if (!strcmp(args[0], "tune.bufsize")) {
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.bufsize = atol(args[1]);
527 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
528 global.tune.maxrewrite = global.tune.bufsize / 2;
529 }
530 else if (!strcmp(args[0], "tune.maxrewrite")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.maxrewrite = atol(args[1]);
537 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
538 global.tune.maxrewrite = global.tune.bufsize / 2;
539 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100540 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
541 if (global.tune.client_rcvbuf != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT;
544 goto out;
545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
550 }
551 global.tune.client_rcvbuf = atol(args[1]);
552 }
553 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
554 if (global.tune.server_rcvbuf != 0) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.server_rcvbuf = atol(args[1]);
565 }
566 else if (!strcmp(args[0], "tune.sndbuf.client")) {
567 if (global.tune.client_sndbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_sndbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.sndbuf.server")) {
580 if (global.tune.server_sndbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_sndbuf = atol(args[1]);
591 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200592 else if (!strcmp(args[0], "tune.pipesize")) {
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.pipesize = atol(args[1]);
599 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200600 else if (!strcmp(args[0], "tune.http.maxhdr")) {
601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.max_http_hdr = atol(args[1]);
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "uid")) {
609 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200610 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 }
619 global.uid = atol(args[1]);
620 }
621 else if (!strcmp(args[0], "gid")) {
622 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200624 err_code |= ERR_ALERT;
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 global.gid = atol(args[1]);
633 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200634 /* user/group name handling */
635 else if (!strcmp(args[0], "user")) {
636 struct passwd *ha_user;
637 if (global.uid != 0) {
638 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT;
640 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 }
642 errno = 0;
643 ha_user = getpwnam(args[1]);
644 if (ha_user != NULL) {
645 global.uid = (int)ha_user->pw_uid;
646 }
647 else {
648 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 +0200649 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200650 }
651 }
652 else if (!strcmp(args[0], "group")) {
653 struct group *ha_group;
654 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200655 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200656 err_code |= ERR_ALERT;
657 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200658 }
659 errno = 0;
660 ha_group = getgrnam(args[1]);
661 if (ha_group != NULL) {
662 global.gid = (int)ha_group->gr_gid;
663 }
664 else {
665 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 +0200666 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200667 }
668 }
669 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 else if (!strcmp(args[0], "nbproc")) {
671 if (global.nbproc != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 global.nbproc = atol(args[1]);
682 }
683 else if (!strcmp(args[0], "maxconn")) {
684 if (global.maxconn != 0) {
685 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 global.maxconn = atol(args[1]);
695#ifdef SYSTEM_MAXCONN
696 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
697 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);
698 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 }
701#endif /* SYSTEM_MAXCONN */
702 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200703 else if (!strcmp(args[0], "maxconnrate")) {
704 if (global.cps_lim != 0) {
705 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
706 err_code |= ERR_ALERT;
707 goto out;
708 }
709 if (*(args[1]) == 0) {
710 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
711 err_code |= ERR_ALERT | ERR_FATAL;
712 goto out;
713 }
714 global.cps_lim = atol(args[1]);
715 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100716 else if (!strcmp(args[0], "maxpipes")) {
717 if (global.maxpipes != 0) {
718 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT;
720 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100721 }
722 if (*(args[1]) == 0) {
723 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 }
727 global.maxpipes = atol(args[1]);
728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 else if (!strcmp(args[0], "ulimit-n")) {
730 if (global.rlimit_nofile != 0) {
731 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740 global.rlimit_nofile = atol(args[1]);
741 }
742 else if (!strcmp(args[0], "chroot")) {
743 if (global.chroot != NULL) {
744 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT;
746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 if (*(args[1]) == 0) {
749 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 global.chroot = strdup(args[1]);
754 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 else if (!strcmp(args[0], "description")) {
756 int i, len=0;
757 char *d;
758
759 if (!*args[1]) {
760 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 for(i=1; *args[i]; i++)
767 len += strlen(args[i])+1;
768
769 if (global.desc)
770 free(global.desc);
771
772 global.desc = d = (char *)calloc(1, len);
773
774 d += sprintf(d, "%s", args[1]);
775 for(i=2; *args[i]; i++)
776 d += sprintf(d, " %s", args[i]);
777 }
778 else if (!strcmp(args[0], "node")) {
779 int i;
780 char c;
781
782 for (i=0; args[1][i]; i++) {
783 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100784 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
785 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200786 break;
787 }
788
789 if (!i || args[1][i]) {
790 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
791 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
792 file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796
797 if (global.node)
798 free(global.node);
799
800 global.node = strdup(args[1]);
801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 else if (!strcmp(args[0], "pidfile")) {
803 if (global.pidfile != NULL) {
804 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 if (*(args[1]) == 0) {
809 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 global.pidfile = strdup(args[1]);
814 }
Emeric Bruned760922010-10-22 17:59:25 +0200815 else if (!strcmp(args[0], "unix-bind")) {
816 int cur_arg = 1;
817 while (*(args[cur_arg])) {
818 if (!strcmp(args[cur_arg], "prefix")) {
819 if (global.unix_bind.prefix != NULL) {
820 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
821 err_code |= ERR_ALERT;
822 cur_arg += 2;
823 continue;
824 }
825
826 if (*(args[cur_arg+1]) == 0) {
827 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 global.unix_bind.prefix = strdup(args[cur_arg+1]);
832 cur_arg += 2;
833 continue;
834 }
835
836 if (!strcmp(args[cur_arg], "mode")) {
837
838 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
839 cur_arg += 2;
840 continue;
841 }
842
843 if (!strcmp(args[cur_arg], "uid")) {
844
845 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
846 cur_arg += 2;
847 continue;
848 }
849
850 if (!strcmp(args[cur_arg], "gid")) {
851
852 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
853 cur_arg += 2;
854 continue;
855 }
856
857 if (!strcmp(args[cur_arg], "user")) {
858 struct passwd *user;
859
860 user = getpwnam(args[cur_arg + 1]);
861 if (!user) {
862 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
863 file, linenum, args[0], args[cur_arg + 1 ]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 global.unix_bind.ux.uid = user->pw_uid;
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "group")) {
874 struct group *group;
875
876 group = getgrnam(args[cur_arg + 1]);
877 if (!group) {
878 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
879 file, linenum, args[0], args[cur_arg + 1 ]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883
884 global.unix_bind.ux.gid = group->gr_gid;
885 cur_arg += 2;
886 continue;
887 }
888
Willy Tarreaub48f9582011-09-05 01:17:06 +0200889 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200890 file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 }
William Lallemand0f99e342011-10-12 17:50:54 +0200895 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
896 /* delete previous herited or defined syslog servers */
897 struct logsrv *back;
898 struct logsrv *tmp;
899
900 if (*(args[1]) != 0) {
901 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905
906 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
907 LIST_DEL(&tmp->list);
908 free(tmp);
909 }
910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200912 struct logsrv *logsrv;
913
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 if (*(args[1]) == 0 || *(args[2]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
William Lallemand0f99e342011-10-12 17:50:54 +0200919
920 logsrv = calloc(1, sizeof(struct logsrv));
921
922 logsrv->facility = get_log_facility(args[2]);
923 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200926 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928
William Lallemand0f99e342011-10-12 17:50:54 +0200929 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200931 logsrv->level = get_log_level(args[3]);
932 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200934 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200935 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
937 }
938
William Lallemand0f99e342011-10-12 17:50:54 +0200939 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200940 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->minlvl = get_log_level(args[4]);
942 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200943 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200946 }
947 }
948
Robert Tsai81ae1952007-12-05 10:47:29 +0100949 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100950 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100951 if (!sk) {
952 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100953 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100954 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200955 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100956 goto out;
957 }
William Lallemand0f99e342011-10-12 17:50:54 +0200958 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100960 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100961 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100962 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
963 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200964 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100965 goto out;
966 }
William Lallemand0f99e342011-10-12 17:50:54 +0200967 logsrv->addr = *sk;
968 if (!get_host_port(&logsrv->addr))
969 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971
William Lallemand0f99e342011-10-12 17:50:54 +0200972 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200973 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100974 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
975 char *name;
976 int len;
977
978 if (global.log_send_hostname != NULL) {
979 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
980 err_code |= ERR_ALERT;
981 goto out;
982 }
983
984 if (*(args[1]))
985 name = args[1];
986 else
987 name = hostname;
988
989 len = strlen(name);
990
991 /* We'll add a space after the name to respect the log format */
992 free(global.log_send_hostname);
993 global.log_send_hostname = malloc(len + 2);
994 snprintf(global.log_send_hostname, len + 2, "%s ", name);
995 }
Kevinm48936af2010-12-22 16:08:21 +0000996 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 free(global.log_tag);
1003 global.log_tag = strdup(args[1]);
1004 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1006 if (global.spread_checks != 0) {
1007 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
1016 global.spread_checks = atol(args[1]);
1017 if (global.spread_checks < 0 || global.spread_checks > 50) {
1018 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001023 struct cfg_kw_list *kwl;
1024 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001025 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001026
1027 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1028 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1029 if (kwl->kw[index].section != CFG_GLOBAL)
1030 continue;
1031 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1032 /* prepare error message just in case */
1033 snprintf(trash, sizeof(trash),
1034 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1036 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001037 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001038 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001039 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001040 else if (rc > 0) {
1041 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_WARN;
1043 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001044 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001046 }
1047 }
1048 }
1049
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001053
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 out:
1055 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056}
1057
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001058void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001060 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 defproxy.mode = PR_MODE_TCP;
1062 defproxy.state = PR_STNEW;
1063 defproxy.maxconn = cfg_maxpconn;
1064 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001065
1066 defproxy.defsrv.inter = DEF_CHKINTR;
1067 defproxy.defsrv.fastinter = 0;
1068 defproxy.defsrv.downinter = 0;
1069 defproxy.defsrv.rise = DEF_RISETIME;
1070 defproxy.defsrv.fall = DEF_FALLTIME;
1071 defproxy.defsrv.check_port = 0;
1072 defproxy.defsrv.maxqueue = 0;
1073 defproxy.defsrv.minconn = 0;
1074 defproxy.defsrv.maxconn = 0;
1075 defproxy.defsrv.slowstart = 0;
1076 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1077 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1078 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079}
1080
Willy Tarreauade5ec42010-01-28 19:33:49 +01001081
1082static int create_cond_regex_rule(const char *file, int line,
1083 struct proxy *px, int dir, int action, int flags,
1084 const char *cmd, const char *reg, const char *repl,
1085 const char **cond_start)
1086{
1087 regex_t *preg = NULL;
1088 const char *err;
1089 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001090 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001091
1092 if (px == &defproxy) {
1093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto err;
1096 }
1097
1098 if (*reg == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto err;
1102 }
1103
1104 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1105 err_code |= ERR_WARN;
1106
Willy Tarreau5321c422010-01-28 20:35:13 +01001107 if (cond_start &&
1108 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1109 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1110 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1111 file, line, cmd);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115 }
1116 else if (cond_start && **cond_start) {
1117 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1118 file, line, cmd, *cond_start);
1119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto err;
1121 }
1122
1123 if (dir == ACL_DIR_REQ)
1124 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001125 else
1126 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001127
Willy Tarreauade5ec42010-01-28 19:33:49 +01001128 preg = calloc(1, sizeof(regex_t));
1129 if (!preg) {
1130 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1131 err_code = ERR_ALERT | ERR_FATAL;
1132 goto err;
1133 }
1134
1135 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1136 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1137 err_code = ERR_ALERT | ERR_FATAL;
1138 goto err;
1139 }
1140
1141 err = chain_regex((dir == ACL_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001142 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001143 if (repl && err) {
1144 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1145 file, line, cmd, *err);
1146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto err;
1148 }
1149
1150 if (dir == ACL_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
1151 err_code |= ERR_WARN;
1152
1153 return err_code;
1154 err:
1155 free(preg);
1156 return err_code;
1157}
1158
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001160 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001161 * Returns the error code, 0 if OK, or any combination of :
1162 * - ERR_ABORT: must abort ASAP
1163 * - ERR_FATAL: we can continue parsing but not start the service
1164 * - ERR_WARN: a warning has been emitted
1165 * - ERR_ALERT: an alert has been emitted
1166 * Only the two first ones can stop processing, the two others are just
1167 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001169int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1170{
1171 static struct peers *curpeers = NULL;
1172 struct peer *newpeer = NULL;
1173 const char *err;
1174 int err_code = 0;
1175
1176 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1177
1178 err = invalid_char(args[1]);
1179 if (err) {
1180 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1181 file, linenum, *err, args[0], args[1]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 }
1184
1185 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1186 /*
1187 * If there are two proxies with the same name only following
1188 * combinations are allowed:
1189 */
1190 if (strcmp(curpeers->id, args[1]) == 0) {
1191 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1192 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1193 err_code |= ERR_WARN;
1194 }
1195 }
1196
1197 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1199 err_code |= ERR_ALERT | ERR_ABORT;
1200 goto out;
1201 }
1202
1203 curpeers->next = peers;
1204 peers = curpeers;
1205 curpeers->conf.file = file;
1206 curpeers->conf.line = linenum;
1207 curpeers->last_change = now.tv_sec;
1208 curpeers->id = strdup(args[1]);
1209 }
1210 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1211 char *rport, *raddr;
1212 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001213 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001214
1215 if (!*args[2]) {
1216 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1217 file, linenum, args[0]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221
1222 err = invalid_char(args[1]);
1223 if (err) {
1224 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1225 file, linenum, *err, args[1]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1231 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1232 err_code |= ERR_ALERT | ERR_ABORT;
1233 goto out;
1234 }
1235
1236 /* the peers are linked backwards first */
1237 curpeers->count++;
1238 newpeer->next = curpeers->remote;
1239 curpeers->remote = newpeer;
1240 newpeer->peers = curpeers;
1241 newpeer->conf.file = file;
1242 newpeer->conf.line = linenum;
1243
1244 newpeer->last_change = now.tv_sec;
1245 newpeer->id = strdup(args[1]);
1246
1247 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001248 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001249 if (rport) {
1250 *rport++ = 0;
1251 realport = atol(rport);
1252 }
1253 if (!realport) {
1254 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258
Willy Tarreaufab5a432011-03-04 15:31:53 +01001259 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001260 free(raddr);
1261 if (!sk) {
1262 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
1265 }
1266 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001267 set_host_port(&newpeer->addr, realport);
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 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001279
Willy Tarreau237250c2011-07-29 01:49:03 +02001280 init_new_proxy(curpeers->peers_fe);
1281 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001282
1283 curpeers->peers_fe->last_change = now.tv_sec;
1284 curpeers->peers_fe->id = strdup(args[1]);
1285 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001286 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001287 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1288 curpeers->peers_fe->timeout.connect = 5000;
1289 curpeers->peers_fe->accept = peer_accept;
1290 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001291 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001292 err_code |= ERR_FATAL;
1293 goto out;
1294 }
1295 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1296 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1297 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1298 curpeers->peers_fe->listen->accept = session_accept;
1299 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1300 curpeers->peers_fe->listen->handler = process_session;
1301 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001302 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1303 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001304 }
1305 }
1306 } /* neither "peer" nor "peers" */
1307 else if (*args[0] != 0) {
1308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
1311 }
1312
1313out:
1314 return err_code;
1315}
1316
1317
Willy Tarreau3842f002009-06-14 11:39:52 +02001318int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319{
1320 static struct proxy *curproxy = NULL;
1321 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001322 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001323 int rc;
1324 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001325 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001326 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001327 struct logsrv *tmplogsrv;
1328 struct logformat_node *tmplf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329
Willy Tarreau977b8e42006-12-29 14:19:17 +01001330 if (!strcmp(args[0], "listen"))
1331 rc = PR_CAP_LISTEN;
1332 else if (!strcmp(args[0], "frontend"))
1333 rc = PR_CAP_FE | PR_CAP_RS;
1334 else if (!strcmp(args[0], "backend"))
1335 rc = PR_CAP_BE | PR_CAP_RS;
1336 else if (!strcmp(args[0], "ruleset"))
1337 rc = PR_CAP_RS;
1338 else
1339 rc = PR_CAP_NONE;
1340
1341 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 if (!*args[1]) {
1343 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1344 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001346 err_code |= ERR_ALERT | ERR_ABORT;
1347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001349
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001350 err = invalid_char(args[1]);
1351 if (err) {
1352 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1353 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001354 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001355 }
1356
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001357 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1358 /*
1359 * If there are two proxies with the same name only following
1360 * combinations are allowed:
1361 *
1362 * listen backend frontend ruleset
1363 * listen - - - -
1364 * backend - - OK -
1365 * frontend - OK - -
1366 * ruleset - - - -
1367 */
1368
1369 if (!strcmp(curproxy->id, args[1]) &&
1370 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1371 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001372 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1373 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1374 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001375 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001376 }
1377 }
1378
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1380 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_ALERT | ERR_ABORT;
1382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001384
Willy Tarreau97cb7802010-01-03 20:23:58 +01001385 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 curproxy->next = proxy;
1387 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001388 curproxy->conf.file = file;
1389 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001390 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001392 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393
1394 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001395 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001396 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001397 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_FATAL;
1399 goto out;
1400 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001401 new = curproxy->listen;
1402 while (new != last) {
1403 new->conf.file = file;
1404 new->conf.line = linenum;
1405 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001406 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001407 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 }
1409
1410 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001411 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001412 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001413
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001416 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001417 curproxy->no_options = defproxy.no_options;
1418 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001419 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001420 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001421 curproxy->except_net = defproxy.except_net;
1422 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001423 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001424 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001426 if (defproxy.fwdfor_hdr_len) {
1427 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1428 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1429 }
1430
Willy Tarreaub86db342009-11-30 11:50:16 +01001431 if (defproxy.orgto_hdr_len) {
1432 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1433 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1434 }
1435
Mark Lamourinec2247f02012-01-04 13:02:01 -05001436 if (defproxy.server_id_hdr_len) {
1437 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1438 curproxy->server_id_hdr_name = strdup(defproxy.server_id_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 Tarreau1ee51a62011-08-19 20:04:17 +02001463 if (defproxy.expect_str) {
1464 curproxy->expect_str = strdup(defproxy.expect_str);
1465 if (defproxy.expect_regex) {
1466 /* note: this regex is known to be valid */
1467 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1468 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1469 }
1470 }
1471
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 if (defproxy.cookie_name)
1473 curproxy->cookie_name = strdup(defproxy.cookie_name);
1474 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001475 if (defproxy.cookie_domain)
1476 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001477
Willy Tarreau31936852010-10-06 16:59:56 +02001478 if (defproxy.cookie_maxidle)
1479 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1480
1481 if (defproxy.cookie_maxlife)
1482 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1483
Emeric Brun647caf12009-06-30 17:57:00 +02001484 if (defproxy.rdp_cookie_name)
1485 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1486 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1487
Willy Tarreau01732802007-11-01 22:48:15 +01001488 if (defproxy.url_param_name)
1489 curproxy->url_param_name = strdup(defproxy.url_param_name);
1490 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001491
Benoitaffb4812009-03-25 13:02:10 +01001492 if (defproxy.hh_name)
1493 curproxy->hh_name = strdup(defproxy.hh_name);
1494 curproxy->hh_len = defproxy.hh_len;
1495 curproxy->hh_match_domain = defproxy.hh_match_domain;
1496
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001497 if (defproxy.iface_name)
1498 curproxy->iface_name = strdup(defproxy.iface_name);
1499 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001502 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503 if (defproxy.capture_name)
1504 curproxy->capture_name = strdup(defproxy.capture_name);
1505 curproxy->capture_namelen = defproxy.capture_namelen;
1506 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508
Willy Tarreau977b8e42006-12-29 14:19:17 +01001509 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001510 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001511 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001512 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001513 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 curproxy->uri_auth = defproxy.uri_auth;
1515 curproxy->mon_net = defproxy.mon_net;
1516 curproxy->mon_mask = defproxy.mon_mask;
1517 if (defproxy.monitor_uri)
1518 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1519 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001520 if (defproxy.defbe.name)
1521 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001522 }
1523
1524 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001525 curproxy->timeout.connect = defproxy.timeout.connect;
1526 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001527 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001528 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001529 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001530 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001531 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001532 curproxy->source_addr = defproxy.source_addr;
1533 }
1534
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001536
1537 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001538 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001539 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001540 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001541 LIST_INIT(&node->list);
1542 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1543 }
1544
William Lallemand723b73a2012-02-08 16:37:49 +01001545 /* copy default log_format to curproxy */
1546 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1547 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1548 memcpy(node, tmplf, sizeof(struct logformat_node));
1549 LIST_INIT(&node->list);
1550 LIST_ADDQ(&curproxy->logformat, &node->list);
1551 }
1552
Willy Tarreaubaaee002006-06-26 02:48:02 +02001553 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001554 curproxy->conf.used_listener_id = EB_ROOT;
1555 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001556
Willy Tarreau93893792009-07-23 13:19:11 +02001557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 }
1559 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1560 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001561 /* FIXME-20070101: we should do this too at the end of the
1562 * config parsing to free all default values.
1563 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001564 free(defproxy.check_req);
1565 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001566 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001567 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001568 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001569 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001570 free(defproxy.capture_name);
1571 free(defproxy.monitor_uri);
1572 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001573 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001574 free(defproxy.fwdfor_hdr_name);
1575 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001576 free(defproxy.orgto_hdr_name);
1577 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001578 free(defproxy.server_id_hdr_name);
1579 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001580 free(defproxy.expect_str);
1581 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001582
Willy Tarreaua534fea2008-08-03 12:19:50 +02001583 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001584 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001585
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 /* we cannot free uri_auth because it might already be used */
1587 init_default_instance();
1588 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001589 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 }
1592 else if (curproxy == NULL) {
1593 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 }
1597
Willy Tarreau977b8e42006-12-29 14:19:17 +01001598
1599 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001601 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001602 int cur_arg;
1603
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 if (curproxy == &defproxy) {
1605 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001606 err_code |= ERR_ALERT | ERR_FATAL;
1607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001609 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611
Emeric Bruned760922010-10-22 17:59:25 +02001612 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001613 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001615 err_code |= ERR_ALERT | ERR_FATAL;
1616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001618
1619 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001620
1621 /* NOTE: the following line might create several listeners if there
1622 * are comma-separated IPs or port ranges. So all further processing
1623 * will have to be applied to all listeners created after last_listen.
1624 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001625 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
1628 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001629
Willy Tarreau90a570f2009-10-04 20:54:54 +02001630 new_listen = curproxy->listen;
1631 while (new_listen != last_listen) {
1632 new_listen->conf.file = file;
1633 new_listen->conf.line = linenum;
1634 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001635 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001636 }
1637
Emeric Bruned760922010-10-22 17:59:25 +02001638 /* Set default global rights and owner for unix bind */
1639 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1640 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1641 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001642 cur_arg = 2;
1643 while (*(args[cur_arg])) {
1644 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1645#ifdef SO_BINDTODEVICE
1646 struct listener *l;
1647
Emeric Bruned760922010-10-22 17:59:25 +02001648 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1649 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1650 file, linenum, args[0], args[cur_arg]);
1651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
1653 }
1654
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001655 if (!*args[cur_arg + 1]) {
1656 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1657 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001658 err_code |= ERR_ALERT | ERR_FATAL;
1659 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001660 }
1661
1662 for (l = curproxy->listen; l != last_listen; l = l->next)
1663 l->interface = strdup(args[cur_arg + 1]);
1664
1665 global.last_checks |= LSTCHK_NETADM;
1666
1667 cur_arg += 2;
1668 continue;
1669#else
1670 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1671 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001672 err_code |= ERR_ALERT | ERR_FATAL;
1673 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001674#endif
1675 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001676 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1677#ifdef TCP_MAXSEG
1678 struct listener *l;
1679 int mss;
1680
Emeric Bruned760922010-10-22 17:59:25 +02001681 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1682 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1683 file, linenum, args[0], args[cur_arg]);
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687
Willy Tarreaube1b9182009-06-14 18:48:19 +02001688 if (!*args[cur_arg + 1]) {
1689 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1690 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001691 err_code |= ERR_ALERT | ERR_FATAL;
1692 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001693 }
1694
Willy Tarreau48a7e722010-12-24 15:26:39 +01001695 mss = atoi(args[cur_arg + 1]);
1696 if (!mss || abs(mss) > 65535) {
1697 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001698 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001699 err_code |= ERR_ALERT | ERR_FATAL;
1700 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001701 }
1702
1703 for (l = curproxy->listen; l != last_listen; l = l->next)
1704 l->maxseg = mss;
1705
1706 cur_arg += 2;
1707 continue;
1708#else
1709 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1710 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001713#endif
1714 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001715
1716 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1717#ifdef TCP_DEFER_ACCEPT
1718 struct listener *l;
1719
1720 for (l = curproxy->listen; l != last_listen; l = l->next)
1721 l->options |= LI_O_DEF_ACCEPT;
1722
1723 cur_arg ++;
1724 continue;
1725#else
1726 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1727 file, linenum, args[0], args[cur_arg]);
1728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
1730#endif
1731 }
1732
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001733 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001734#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001735 struct listener *l;
1736
Emeric Bruned760922010-10-22 17:59:25 +02001737 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1738 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1739 file, linenum, args[0], args[cur_arg]);
1740 err_code |= ERR_ALERT | ERR_FATAL;
1741 goto out;
1742 }
1743
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001744 for (l = curproxy->listen; l != last_listen; l = l->next)
1745 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001746
1747 cur_arg ++;
1748 continue;
1749#else
1750 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1751 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001754#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001755 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001756
Willy Tarreau8a956912010-10-15 14:27:08 +02001757 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1758 struct listener *l;
1759
1760 for (l = curproxy->listen; l != last_listen; l = l->next)
1761 l->options |= LI_O_ACC_PROXY;
1762
1763 cur_arg ++;
1764 continue;
1765 }
1766
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001767 if (!strcmp(args[cur_arg], "name")) {
1768 struct listener *l;
1769
1770 for (l = curproxy->listen; l != last_listen; l = l->next)
1771 l->name = strdup(args[cur_arg + 1]);
1772
1773 cur_arg += 2;
1774 continue;
1775 }
1776
1777 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001778 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779 struct listener *l;
1780
1781 if (curproxy->listen->next != last_listen) {
1782 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1783 file, linenum, args[cur_arg]);
1784 err_code |= ERR_ALERT | ERR_FATAL;
1785 goto out;
1786 }
1787
1788 if (!*args[cur_arg + 1]) {
1789 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1790 file, linenum, args[cur_arg]);
1791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
1793 }
1794
1795 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001796 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001797
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001798 if (curproxy->listen->luid <= 0) {
1799 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001800 file, linenum);
1801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
1803 }
1804
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001805 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1806 if (node) {
1807 l = container_of(node, struct listener, conf.id);
1808 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1809 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
1813 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1814
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001815 cur_arg += 2;
1816 continue;
1817 }
1818
Emeric Bruned760922010-10-22 17:59:25 +02001819 if (!strcmp(args[cur_arg], "mode")) {
1820
1821 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1822 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1823 file, linenum, args[0], args[cur_arg]);
1824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1829
1830 cur_arg += 2;
1831 continue;
1832 }
1833
1834 if (!strcmp(args[cur_arg], "uid")) {
1835
1836 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1837 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1838 file, linenum, args[0], args[cur_arg]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842
1843 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1844 cur_arg += 2;
1845 continue;
1846 }
1847
1848 if (!strcmp(args[cur_arg], "gid")) {
1849
1850 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1851 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1852 file, linenum, args[0], args[cur_arg]);
1853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
1855 }
1856
1857 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1858 cur_arg += 2;
1859 continue;
1860 }
1861
1862 if (!strcmp(args[cur_arg], "user")) {
1863 struct passwd *user;
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 user = getpwnam(args[cur_arg + 1]);
1872 if (!user) {
1873 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\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.uid = user->pw_uid;
1880 cur_arg += 2;
1881 continue;
1882 }
1883
1884 if (!strcmp(args[cur_arg], "group")) {
1885 struct group *group;
1886
1887 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1888 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1889 file, linenum, args[0], args[cur_arg]);
1890 err_code |= ERR_ALERT | ERR_FATAL;
1891 goto out;
1892 }
1893 group = getgrnam(args[cur_arg + 1]);
1894 if (!group) {
1895 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1896 file, linenum, args[0], args[cur_arg + 1 ]);
1897 err_code |= ERR_ALERT | ERR_FATAL;
1898 goto out;
1899 }
1900
1901 curproxy->listen->perm.ux.gid = group->gr_gid;
1902 cur_arg += 2;
1903 continue;
1904 }
1905
Willy Tarreaub48f9582011-09-05 01:17:06 +02001906 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001907 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001910 }
Willy Tarreau93893792009-07-23 13:19:11 +02001911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912 }
1913 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1914 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1915 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001917 err_code |= ERR_ALERT | ERR_FATAL;
1918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001919 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001920 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001922
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 /* flush useless bits */
1924 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001927 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001930
Willy Tarreau1c47f852006-07-09 08:22:27 +02001931 if (!*args[1]) {
1932 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_FATAL;
1935 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001936 }
1937
Willy Tarreaua534fea2008-08-03 12:19:50 +02001938 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001939 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001940 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001941 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001942 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1943
Willy Tarreau93893792009-07-23 13:19:11 +02001944 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001945 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1947 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1948 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1949 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1950 else {
1951 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001954 }
1955 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001956 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001957 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001958
1959 if (curproxy == &defproxy) {
1960 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1961 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001962 err_code |= ERR_ALERT | ERR_FATAL;
1963 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001964 }
1965
1966 if (!*args[1]) {
1967 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1968 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001969 err_code |= ERR_ALERT | ERR_FATAL;
1970 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001971 }
1972
1973 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001974 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001975
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001976 if (curproxy->uuid <= 0) {
1977 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001978 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001979 err_code |= ERR_ALERT | ERR_FATAL;
1980 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001981 }
1982
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001983 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1984 if (node) {
1985 struct proxy *target = container_of(node, struct proxy, conf.id);
1986 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1987 file, linenum, proxy_type_str(curproxy), curproxy->id,
1988 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
1991 }
1992 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001993 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001994 else if (!strcmp(args[0], "description")) {
1995 int i, len=0;
1996 char *d;
1997
Cyril Bonté99ed3272010-01-24 23:29:44 +01001998 if (curproxy == &defproxy) {
1999 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2000 file, linenum, args[0]);
2001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
2003 }
2004
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002005 if (!*args[1]) {
2006 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2007 file, linenum, args[0]);
2008 return -1;
2009 }
2010
2011 for(i=1; *args[i]; i++)
2012 len += strlen(args[i])+1;
2013
2014 d = (char *)calloc(1, len);
2015 curproxy->desc = d;
2016
2017 d += sprintf(d, "%s", args[1]);
2018 for(i=2; *args[i]; i++)
2019 d += sprintf(d, " %s", args[i]);
2020
2021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2023 curproxy->state = PR_STSTOPPED;
2024 }
2025 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2026 curproxy->state = PR_STNEW;
2027 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002028 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2029 int cur_arg = 1;
2030 unsigned int set = 0;
2031
2032 while (*args[cur_arg]) {
2033 int u;
2034 if (strcmp(args[cur_arg], "all") == 0) {
2035 set = 0;
2036 break;
2037 }
2038 else if (strcmp(args[cur_arg], "odd") == 0) {
2039 set |= 0x55555555;
2040 }
2041 else if (strcmp(args[cur_arg], "even") == 0) {
2042 set |= 0xAAAAAAAA;
2043 }
2044 else {
2045 u = str2uic(args[cur_arg]);
2046 if (u < 1 || u > 32) {
2047 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2048 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002051 }
2052 if (u > global.nbproc) {
2053 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2054 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002055 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002056 }
2057 set |= 1 << (u - 1);
2058 }
2059 cur_arg++;
2060 }
2061 curproxy->bind_proc = set;
2062 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002063 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002064 if (curproxy == &defproxy) {
2065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002066 err_code |= ERR_ALERT | ERR_FATAL;
2067 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002068 }
2069
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002070 err = invalid_char(args[1]);
2071 if (err) {
2072 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2073 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002075 }
2076
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002077 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2078 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2079 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002082 }
2083 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2085 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002086
Willy Tarreau977b8e42006-12-29 14:19:17 +01002087 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002088 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002089
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090 if (*(args[1]) == 0) {
2091 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_ALERT | ERR_FATAL;
2094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002096
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002097 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002098 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002099 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002100 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002101 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 curproxy->cookie_name = strdup(args[1]);
2103 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002104
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 cur_arg = 2;
2106 while (*(args[cur_arg])) {
2107 if (!strcmp(args[cur_arg], "rewrite")) {
2108 curproxy->options |= PR_O_COOK_RW;
2109 }
2110 else if (!strcmp(args[cur_arg], "indirect")) {
2111 curproxy->options |= PR_O_COOK_IND;
2112 }
2113 else if (!strcmp(args[cur_arg], "insert")) {
2114 curproxy->options |= PR_O_COOK_INS;
2115 }
2116 else if (!strcmp(args[cur_arg], "nocache")) {
2117 curproxy->options |= PR_O_COOK_NOC;
2118 }
2119 else if (!strcmp(args[cur_arg], "postonly")) {
2120 curproxy->options |= PR_O_COOK_POST;
2121 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002122 else if (!strcmp(args[cur_arg], "preserve")) {
2123 curproxy->options2 |= PR_O2_COOK_PSV;
2124 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 else if (!strcmp(args[cur_arg], "prefix")) {
2126 curproxy->options |= PR_O_COOK_PFX;
2127 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002128 else if (!strcmp(args[cur_arg], "domain")) {
2129 if (!*args[cur_arg + 1]) {
2130 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2131 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002134 }
2135
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002136 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002137 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002138 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2139 " dots nor does not start with a dot."
2140 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002141 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002142 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002143 }
2144
2145 err = invalid_domainchar(args[cur_arg + 1]);
2146 if (err) {
2147 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2148 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002151 }
2152
Willy Tarreau68a897b2009-12-03 23:28:34 +01002153 if (!curproxy->cookie_domain) {
2154 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2155 } else {
2156 /* one domain was already specified, add another one by
2157 * building the string which will be returned along with
2158 * the cookie.
2159 */
2160 char *new_ptr;
2161 int new_len = strlen(curproxy->cookie_domain) +
2162 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2163 new_ptr = malloc(new_len);
2164 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2165 free(curproxy->cookie_domain);
2166 curproxy->cookie_domain = new_ptr;
2167 }
Willy Tarreau31936852010-10-06 16:59:56 +02002168 cur_arg++;
2169 }
2170 else if (!strcmp(args[cur_arg], "maxidle")) {
2171 unsigned int maxidle;
2172 const char *res;
2173
2174 if (!*args[cur_arg + 1]) {
2175 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2176 file, linenum, args[cur_arg]);
2177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
2179 }
2180
2181 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2182 if (res) {
2183 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2184 file, linenum, *res, args[cur_arg]);
2185 err_code |= ERR_ALERT | ERR_FATAL;
2186 goto out;
2187 }
2188 curproxy->cookie_maxidle = maxidle;
2189 cur_arg++;
2190 }
2191 else if (!strcmp(args[cur_arg], "maxlife")) {
2192 unsigned int maxlife;
2193 const char *res;
2194
2195 if (!*args[cur_arg + 1]) {
2196 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2197 file, linenum, args[cur_arg]);
2198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
2200 }
2201
2202 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2203 if (res) {
2204 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2205 file, linenum, *res, args[cur_arg]);
2206 err_code |= ERR_ALERT | ERR_FATAL;
2207 goto out;
2208 }
2209 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002210 cur_arg++;
2211 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002212 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002213 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 +02002214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002217 }
2218 cur_arg++;
2219 }
2220 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2221 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2222 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002223 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 }
2225
2226 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2227 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2228 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002229 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002230 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002231
2232 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2233 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2234 file, linenum);
2235 err_code |= ERR_ALERT | ERR_FATAL;
2236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002237 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002238 else if (!strcmp(args[0], "persist")) { /* persist */
2239 if (*(args[1]) == 0) {
2240 Alert("parsing [%s:%d] : missing persist method.\n",
2241 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002244 }
2245
2246 if (!strncmp(args[1], "rdp-cookie", 10)) {
2247 curproxy->options2 |= PR_O2_RDPC_PRST;
2248
Emeric Brunb982a3d2010-01-04 15:45:53 +01002249 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002250 const char *beg, *end;
2251
2252 beg = args[1] + 11;
2253 end = strchr(beg, ')');
2254
2255 if (!end || end == beg) {
2256 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2257 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002260 }
2261
2262 free(curproxy->rdp_cookie_name);
2263 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2264 curproxy->rdp_cookie_len = end-beg;
2265 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002266 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002267 free(curproxy->rdp_cookie_name);
2268 curproxy->rdp_cookie_name = strdup("msts");
2269 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2270 }
2271 else { /* syntax */
2272 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2273 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002276 }
2277 }
2278 else {
2279 Alert("parsing [%s:%d] : unknown persist method.\n",
2280 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002283 }
2284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002286 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002288 if (curproxy == &defproxy) {
2289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
2293
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002296
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002298 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 }
2303 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002304 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 curproxy->appsession_name = strdup(args[1]);
2306 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2307 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002308 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2309 if (err) {
2310 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2311 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002314 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002315 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002316
Willy Tarreau51041c72007-09-09 21:56:53 +02002317 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2318 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002319 err_code |= ERR_ALERT | ERR_ABORT;
2320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002322
2323 cur_arg = 6;
2324 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002325 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2326 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002327 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002328 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002329 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002330 } else if (!strcmp(args[cur_arg], "prefix")) {
2331 curproxy->options2 |= PR_O2_AS_PFX;
2332 } else if (!strcmp(args[cur_arg], "mode")) {
2333 if (!*args[cur_arg + 1]) {
2334 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2335 file, linenum, args[0], args[cur_arg]);
2336 err_code |= ERR_ALERT | ERR_FATAL;
2337 goto out;
2338 }
2339
2340 cur_arg++;
2341 if (!strcmp(args[cur_arg], "query-string")) {
2342 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2343 curproxy->options2 |= PR_O2_AS_M_QS;
2344 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2345 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2346 curproxy->options2 |= PR_O2_AS_M_PP;
2347 } else {
2348 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
2351 }
2352 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002353 cur_arg++;
2354 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 } /* Url App Session */
2356 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002357 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002358 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002361 if (curproxy == &defproxy) {
2362 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
2365 }
2366
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 if (*(args[4]) == 0) {
2368 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002373 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002374 curproxy->capture_name = strdup(args[2]);
2375 curproxy->capture_namelen = strlen(curproxy->capture_name);
2376 curproxy->capture_len = atol(args[4]);
2377 if (curproxy->capture_len >= CAPTURE_LEN) {
2378 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2379 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 curproxy->capture_len = CAPTURE_LEN - 1;
2382 }
2383 curproxy->to_log |= LW_COOKIE;
2384 }
2385 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2386 struct cap_hdr *hdr;
2387
2388 if (curproxy == &defproxy) {
2389 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 +02002390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 }
2393
2394 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2395 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2396 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 }
2400
2401 hdr = calloc(sizeof(struct cap_hdr), 1);
2402 hdr->next = curproxy->req_cap;
2403 hdr->name = strdup(args[3]);
2404 hdr->namelen = strlen(args[3]);
2405 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002406 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002407 hdr->index = curproxy->nb_req_cap++;
2408 curproxy->req_cap = hdr;
2409 curproxy->to_log |= LW_REQHDR;
2410 }
2411 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2412 struct cap_hdr *hdr;
2413
2414 if (curproxy == &defproxy) {
2415 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 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 }
2419
2420 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2421 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2422 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 }
2426 hdr = calloc(sizeof(struct cap_hdr), 1);
2427 hdr->next = curproxy->rsp_cap;
2428 hdr->name = strdup(args[3]);
2429 hdr->namelen = strlen(args[3]);
2430 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002431 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 hdr->index = curproxy->nb_rsp_cap++;
2433 curproxy->rsp_cap = hdr;
2434 curproxy->to_log |= LW_RSPHDR;
2435 }
2436 else {
2437 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2438 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002441 }
2442 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002444 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002446
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 if (*(args[1]) == 0) {
2448 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2449 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 }
2453 curproxy->conn_retries = atol(args[1]);
2454 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002455 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002456 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002457
2458 if (curproxy == &defproxy) {
2459 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
2462 }
2463
Willy Tarreauff011f22011-01-06 17:51:27 +01002464 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 +01002465 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2466 file, linenum, args[0]);
2467 err_code |= ERR_WARN;
2468 }
2469
Willy Tarreauff011f22011-01-06 17:51:27 +01002470 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002471
Willy Tarreauff011f22011-01-06 17:51:27 +01002472 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002473 err_code |= ERR_ALERT | ERR_ABORT;
2474 goto out;
2475 }
2476
Willy Tarreauff011f22011-01-06 17:51:27 +01002477 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2478 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002479 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002480 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2481 /* set the header name and length into the proxy structure */
2482 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2483 err_code |= ERR_WARN;
2484
2485 if (!*args[1]) {
2486 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2487 file, linenum, args[0]);
2488 err_code |= ERR_ALERT | ERR_FATAL;
2489 goto out;
2490 }
2491
2492 /* set the desired header name */
2493 free(curproxy->server_id_hdr_name);
2494 curproxy->server_id_hdr_name = strdup(args[1]);
2495 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2496 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002497 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002498 if (curproxy == &defproxy) {
2499 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002502 }
2503
Willy Tarreauef6494c2010-01-28 17:12:36 +01002504 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002505 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2506 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_ALERT | ERR_FATAL;
2508 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002509 }
2510
Willy Tarreauef6494c2010-01-28 17:12:36 +01002511 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002512 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2513 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
2515 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002516 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002517
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002518 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002519 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002520 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002521 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002522 struct redirect_rule *rule;
2523 int cur_arg;
2524 int type = REDIRECT_TYPE_NONE;
2525 int code = 302;
2526 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002527 char *cookie = NULL;
2528 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002529 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002530
Cyril Bonté99ed3272010-01-24 23:29:44 +01002531 if (curproxy == &defproxy) {
2532 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2533 err_code |= ERR_ALERT | ERR_FATAL;
2534 goto out;
2535 }
2536
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002537 cur_arg = 1;
2538 while (*(args[cur_arg])) {
2539 if (!strcmp(args[cur_arg], "location")) {
2540 if (!*args[cur_arg + 1]) {
2541 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2542 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002545 }
2546
2547 type = REDIRECT_TYPE_LOCATION;
2548 cur_arg++;
2549 destination = args[cur_arg];
2550 }
2551 else if (!strcmp(args[cur_arg], "prefix")) {
2552 if (!*args[cur_arg + 1]) {
2553 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2554 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002557 }
2558
2559 type = REDIRECT_TYPE_PREFIX;
2560 cur_arg++;
2561 destination = args[cur_arg];
2562 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002563 else if (!strcmp(args[cur_arg], "set-cookie")) {
2564 if (!*args[cur_arg + 1]) {
2565 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2566 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002569 }
2570
2571 cur_arg++;
2572 cookie = args[cur_arg];
2573 cookie_set = 1;
2574 }
2575 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2576 if (!*args[cur_arg + 1]) {
2577 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2578 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
2580 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002581 }
2582
2583 cur_arg++;
2584 cookie = args[cur_arg];
2585 cookie_set = 0;
2586 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002587 else if (!strcmp(args[cur_arg],"code")) {
2588 if (!*args[cur_arg + 1]) {
2589 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2590 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002593 }
2594 cur_arg++;
2595 code = atol(args[cur_arg]);
2596 if (code < 301 || code > 303) {
2597 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2598 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601 }
2602 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002603 else if (!strcmp(args[cur_arg],"drop-query")) {
2604 flags |= REDIRECT_FLAG_DROP_QS;
2605 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002606 else if (!strcmp(args[cur_arg],"append-slash")) {
2607 flags |= REDIRECT_FLAG_APPEND_SLASH;
2608 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002609 else if (strcmp(args[cur_arg], "if") == 0 ||
2610 strcmp(args[cur_arg], "unless") == 0) {
2611 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2612 if (!cond) {
2613 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2614 file, linenum, args[0]);
2615 err_code |= ERR_ALERT | ERR_FATAL;
2616 goto out;
2617 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002618 break;
2619 }
2620 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002621 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 +02002622 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002625 }
2626 cur_arg++;
2627 }
2628
2629 if (type == REDIRECT_TYPE_NONE) {
2630 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2631 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002634 }
2635
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002636 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2637 rule->cond = cond;
2638 rule->rdr_str = strdup(destination);
2639 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002640 if (cookie) {
2641 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002642 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002643 */
2644 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002645 if (cookie_set) {
2646 rule->cookie_str = malloc(rule->cookie_len + 10);
2647 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2648 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2649 rule->cookie_len += 9;
2650 } else {
2651 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002652 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002653 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2654 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002655 }
2656 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002657 rule->type = type;
2658 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002659 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002660 LIST_INIT(&rule->list);
2661 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002662 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2663 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002664 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002665 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002666 struct switching_rule *rule;
2667
Willy Tarreaub099aca2008-10-12 17:26:37 +02002668 if (curproxy == &defproxy) {
2669 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002672 }
2673
Willy Tarreau55ea7572007-06-17 19:56:27 +02002674 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002676
2677 if (*(args[1]) == 0) {
2678 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002681 }
2682
Willy Tarreauef6494c2010-01-28 17:12:36 +01002683 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002684 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2685 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002688 }
2689
Willy Tarreauef6494c2010-01-28 17:12:36 +01002690 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002691 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002692 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002695 }
2696
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002697 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002698
Willy Tarreau55ea7572007-06-17 19:56:27 +02002699 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2700 rule->cond = cond;
2701 rule->be.name = strdup(args[1]);
2702 LIST_INIT(&rule->list);
2703 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2704 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002705 else if ((!strcmp(args[0], "force-persist")) ||
2706 (!strcmp(args[0], "ignore-persist"))) {
2707 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002708
2709 if (curproxy == &defproxy) {
2710 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714
2715 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2716 err_code |= ERR_WARN;
2717
Willy Tarreauef6494c2010-01-28 17:12:36 +01002718 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002719 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2720 file, linenum, args[0]);
2721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
2723 }
2724
Willy Tarreauef6494c2010-01-28 17:12:36 +01002725 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002726 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2727 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
2730 }
2731
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002732 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002733
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002734 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002735 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002736 if (!strcmp(args[0], "force-persist")) {
2737 rule->type = PERSIST_TYPE_FORCE;
2738 } else {
2739 rule->type = PERSIST_TYPE_IGNORE;
2740 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002741 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002742 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002743 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002744 else if (!strcmp(args[0], "stick-table")) {
2745 int myidx = 1;
2746
Emeric Brun32da3c42010-09-23 18:39:19 +02002747 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002748 curproxy->table.type = (unsigned int)-1;
2749 while (*args[myidx]) {
2750 const char *err;
2751
2752 if (strcmp(args[myidx], "size") == 0) {
2753 myidx++;
2754 if (!*(args[myidx])) {
2755 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2756 file, linenum, args[myidx-1]);
2757 err_code |= ERR_ALERT | ERR_FATAL;
2758 goto out;
2759 }
2760 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2761 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2762 file, linenum, *err, args[myidx-1]);
2763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002766 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002767 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002768 else if (strcmp(args[myidx], "peers") == 0) {
2769 myidx++;
2770 if (!*(args[myidx])) {
2771 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2772 file, linenum, args[myidx-1]);
2773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
2775 }
2776 curproxy->table.peers.name = strdup(args[myidx++]);
2777 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002778 else if (strcmp(args[myidx], "expire") == 0) {
2779 myidx++;
2780 if (!*(args[myidx])) {
2781 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2782 file, linenum, args[myidx-1]);
2783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
2785 }
2786 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2787 if (err) {
2788 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2789 file, linenum, *err, args[myidx-1]);
2790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
2792 }
2793 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002794 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002795 }
2796 else if (strcmp(args[myidx], "nopurge") == 0) {
2797 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002798 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002799 }
2800 else if (strcmp(args[myidx], "type") == 0) {
2801 myidx++;
2802 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2803 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2804 file, linenum, args[myidx]);
2805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002808 /* myidx already points to next arg */
2809 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002810 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002811 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002812 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002813
2814 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002815 nw = args[myidx];
2816 while (*nw) {
2817 /* the "store" keyword supports a comma-separated list */
2818 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002819 sa = NULL; /* store arg */
2820 while (*nw && *nw != ',') {
2821 if (*nw == '(') {
2822 *nw = 0;
2823 sa = ++nw;
2824 while (*nw != ')') {
2825 if (!*nw) {
2826 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2827 file, linenum, args[0], cw);
2828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
2830 }
2831 nw++;
2832 }
2833 *nw = '\0';
2834 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002835 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002836 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002837 if (*nw)
2838 *nw++ = '\0';
2839 type = stktable_get_data_type(cw);
2840 if (type < 0) {
2841 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2842 file, linenum, args[0], cw);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845 }
Willy Tarreauac782882010-06-20 10:41:54 +02002846
2847 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2848 switch (err) {
2849 case PE_NONE: break;
2850 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002851 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2852 file, linenum, args[0], cw);
2853 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002854 break;
2855
2856 case PE_ARG_MISSING:
2857 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2858 file, linenum, args[0], cw);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861
2862 case PE_ARG_NOT_USED:
2863 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2864 file, linenum, args[0], cw);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867
2868 default:
2869 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2870 file, linenum, args[0], cw);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002873 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002874 }
2875 myidx++;
2876 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002877 else {
2878 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2879 file, linenum, args[myidx]);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002882 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002883 }
2884
2885 if (!curproxy->table.size) {
2886 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2887 file, linenum);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891
2892 if (curproxy->table.type == (unsigned int)-1) {
2893 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2894 file, linenum);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
2897 }
2898 }
2899 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002900 struct sticking_rule *rule;
2901 struct pattern_expr *expr;
2902 int myidx = 0;
2903 const char *name = NULL;
2904 int flags;
2905
2906 if (curproxy == &defproxy) {
2907 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2908 err_code |= ERR_ALERT | ERR_FATAL;
2909 goto out;
2910 }
2911
2912 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2913 err_code |= ERR_WARN;
2914 goto out;
2915 }
2916
2917 myidx++;
2918 if ((strcmp(args[myidx], "store") == 0) ||
2919 (strcmp(args[myidx], "store-request") == 0)) {
2920 myidx++;
2921 flags = STK_IS_STORE;
2922 }
2923 else if (strcmp(args[myidx], "store-response") == 0) {
2924 myidx++;
2925 flags = STK_IS_STORE | STK_ON_RSP;
2926 }
2927 else if (strcmp(args[myidx], "match") == 0) {
2928 myidx++;
2929 flags = STK_IS_MATCH;
2930 }
2931 else if (strcmp(args[myidx], "on") == 0) {
2932 myidx++;
2933 flags = STK_IS_MATCH | STK_IS_STORE;
2934 }
2935 else {
2936 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
2939 }
2940
2941 if (*(args[myidx]) == 0) {
2942 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946
Emeric Brun485479d2010-09-23 18:02:19 +02002947 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002948 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002949 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953
2954 if (flags & STK_ON_RSP) {
2955 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2956 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2957 file, linenum, args[0], expr->fetch->kw);
2958 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002959 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 goto out;
2961 }
2962 } else {
2963 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2964 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2965 file, linenum, args[0], expr->fetch->kw);
2966 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002967 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002968 goto out;
2969 }
2970 }
2971
2972 if (strcmp(args[myidx], "table") == 0) {
2973 myidx++;
2974 name = args[myidx++];
2975 }
2976
Willy Tarreauef6494c2010-01-28 17:12:36 +01002977 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
2978 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002979 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2980 file, linenum, args[0]);
2981 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002982 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002983 goto out;
2984 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002985 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002986 else if (*(args[myidx])) {
2987 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2988 file, linenum, args[0], args[myidx]);
2989 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09002990 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002991 goto out;
2992 }
Emeric Brun97679e72010-09-23 17:56:44 +02002993 if (flags & STK_ON_RSP)
2994 err_code |= warnif_cond_requires_req(cond, file, linenum);
2995 else
2996 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002997
Emeric Brunb982a3d2010-01-04 15:45:53 +01002998 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2999 rule->cond = cond;
3000 rule->expr = expr;
3001 rule->flags = flags;
3002 rule->table.name = name ? strdup(name) : NULL;
3003 LIST_INIT(&rule->list);
3004 if (flags & STK_ON_RSP)
3005 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3006 else
3007 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003010 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003012
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3014 curproxy->uri_auth = NULL; /* we must detach from the default config */
3015
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003016 if (!*args[1]) {
3017 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003018 } else if (!strcmp(args[1], "admin")) {
3019 struct stats_admin_rule *rule;
3020
3021 if (curproxy == &defproxy) {
3022 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
3026
3027 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3028 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3029 err_code |= ERR_ALERT | ERR_ABORT;
3030 goto out;
3031 }
3032
3033 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3034 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3035 file, linenum, args[0], args[1]);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038 }
3039 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3040 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3041 file, linenum, args[0], args[1]);
3042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
3044 }
3045
3046 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3047
3048 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3049 rule->cond = cond;
3050 LIST_INIT(&rule->list);
3051 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 } else if (!strcmp(args[1], "uri")) {
3053 if (*(args[2]) == 0) {
3054 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3058 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_ABORT;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
3062 } else if (!strcmp(args[1], "realm")) {
3063 if (*(args[2]) == 0) {
3064 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3068 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003069 err_code |= ERR_ALERT | ERR_ABORT;
3070 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003072 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003073 unsigned interval;
3074
3075 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3076 if (err) {
3077 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3078 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003081 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3082 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_ABORT;
3084 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003085 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003086 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003087 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003088
3089 if (curproxy == &defproxy) {
3090 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
3093 }
3094
3095 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3096 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3097 err_code |= ERR_ALERT | ERR_ABORT;
3098 goto out;
3099 }
3100
Willy Tarreauff011f22011-01-06 17:51:27 +01003101 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3102 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003103 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3104 file, linenum, args[0]);
3105 err_code |= ERR_WARN;
3106 }
3107
Willy Tarreauff011f22011-01-06 17:51:27 +01003108 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003109
Willy Tarreauff011f22011-01-06 17:51:27 +01003110 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003111 err_code |= ERR_ALERT | ERR_ABORT;
3112 goto out;
3113 }
3114
Willy Tarreauff011f22011-01-06 17:51:27 +01003115 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3116 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003117
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 } else if (!strcmp(args[1], "auth")) {
3119 if (*(args[2]) == 0) {
3120 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3124 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_ABORT;
3126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 }
3128 } else if (!strcmp(args[1], "scope")) {
3129 if (*(args[2]) == 0) {
3130 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3134 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003135 err_code |= ERR_ALERT | ERR_ABORT;
3136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 }
3138 } else if (!strcmp(args[1], "enable")) {
3139 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3140 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003141 err_code |= ERR_ALERT | ERR_ABORT;
3142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003144 } else if (!strcmp(args[1], "hide-version")) {
3145 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3146 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003147 err_code |= ERR_ALERT | ERR_ABORT;
3148 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003149 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003150 } else if (!strcmp(args[1], "show-legends")) {
3151 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3152 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3153 err_code |= ERR_ALERT | ERR_ABORT;
3154 goto out;
3155 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003156 } else if (!strcmp(args[1], "show-node")) {
3157
3158 if (*args[2]) {
3159 int i;
3160 char c;
3161
3162 for (i=0; args[2][i]; i++) {
3163 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003164 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3165 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003166 break;
3167 }
3168
3169 if (!i || args[2][i]) {
3170 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3171 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3172 file, linenum, args[0], args[1]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176 }
3177
3178 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3179 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3180 err_code |= ERR_ALERT | ERR_ABORT;
3181 goto out;
3182 }
3183 } else if (!strcmp(args[1], "show-desc")) {
3184 char *desc = NULL;
3185
3186 if (*args[2]) {
3187 int i, len=0;
3188 char *d;
3189
3190 for(i=2; *args[i]; i++)
3191 len += strlen(args[i])+1;
3192
3193 desc = d = (char *)calloc(1, len);
3194
3195 d += sprintf(d, "%s", args[2]);
3196 for(i=3; *args[i]; i++)
3197 d += sprintf(d, " %s", args[i]);
3198 }
3199
3200 if (!*args[2] && !global.desc)
3201 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3202 file, linenum, args[1]);
3203 else {
3204 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3205 free(desc);
3206 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3207 err_code |= ERR_ALERT | ERR_ABORT;
3208 goto out;
3209 }
3210 free(desc);
3211 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003213stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003214 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 +01003215 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 }
3219 }
3220 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003221 int optnum;
3222
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003223 if (*(args[1]) == '\0') {
3224 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3225 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003229
3230 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3231 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003232 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3233 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3234 file, linenum, cfg_opts[optnum].name);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
Willy Tarreau93893792009-07-23 13:19:11 +02003238 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3239 err_code |= ERR_WARN;
3240 goto out;
3241 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003242
Willy Tarreau3842f002009-06-14 11:39:52 +02003243 curproxy->no_options &= ~cfg_opts[optnum].val;
3244 curproxy->options &= ~cfg_opts[optnum].val;
3245
3246 switch (kwm) {
3247 case KWM_STD:
3248 curproxy->options |= cfg_opts[optnum].val;
3249 break;
3250 case KWM_NO:
3251 curproxy->no_options |= cfg_opts[optnum].val;
3252 break;
3253 case KWM_DEF: /* already cleared */
3254 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003255 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003256
Willy Tarreau93893792009-07-23 13:19:11 +02003257 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003258 }
3259 }
3260
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003261 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3262 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003263 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3264 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3265 file, linenum, cfg_opts2[optnum].name);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
Willy Tarreau93893792009-07-23 13:19:11 +02003269 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3270 err_code |= ERR_WARN;
3271 goto out;
3272 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003273
Willy Tarreau3842f002009-06-14 11:39:52 +02003274 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3275 curproxy->options2 &= ~cfg_opts2[optnum].val;
3276
3277 switch (kwm) {
3278 case KWM_STD:
3279 curproxy->options2 |= cfg_opts2[optnum].val;
3280 break;
3281 case KWM_NO:
3282 curproxy->no_options2 |= cfg_opts2[optnum].val;
3283 break;
3284 case KWM_DEF: /* already cleared */
3285 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003286 }
Willy Tarreau93893792009-07-23 13:19:11 +02003287 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003288 }
3289 }
3290
Willy Tarreau3842f002009-06-14 11:39:52 +02003291 if (kwm != KWM_STD) {
3292 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003293 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003296 }
3297
Emeric Brun3a058f32009-06-30 18:26:00 +02003298 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003299 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003301 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
William Lallemand723b73a2012-02-08 16:37:49 +01003303 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003304 if (*(args[2]) != '\0') {
3305 if (!strcmp(args[2], "clf")) {
3306 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003307 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003308 } else {
3309 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003312 }
3313 }
William Lallemand723b73a2012-02-08 16:37:49 +01003314 parse_logformat_string(logformat, curproxy);
Emeric Brun3a058f32009-06-30 18:26:00 +02003315 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003316 else if (!strcmp(args[1], "tcplog")) {
3317 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 /* generate a detailed TCP log */
3319 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003320 logformat = default_tcp_log_format;
3321 parse_logformat_string(logformat, curproxy);
3322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 else if (!strcmp(args[1], "tcpka")) {
3324 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003325 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003327
3328 if (curproxy->cap & PR_CAP_FE)
3329 curproxy->options |= PR_O_TCP_CLI_KA;
3330 if (curproxy->cap & PR_CAP_BE)
3331 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 }
3333 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003334 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_WARN;
3336
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003338 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003339 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003340 curproxy->options2 &= ~PR_O2_CHK_ANY;
3341 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003342 if (!*args[2]) { /* no argument */
3343 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3344 curproxy->check_len = strlen(DEF_CHECK_REQ);
3345 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003346 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 curproxy->check_req = (char *)malloc(reqlen);
3348 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003349 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003351 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003352 if (*args[4])
3353 reqlen += strlen(args[4]);
3354 else
3355 reqlen += strlen("HTTP/1.0");
3356
3357 curproxy->check_req = (char *)malloc(reqlen);
3358 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003359 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003361 }
3362 else if (!strcmp(args[1], "ssl-hello-chk")) {
3363 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003364 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003365 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003366
Willy Tarreaua534fea2008-08-03 12:19:50 +02003367 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003368 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003369 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003370 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003371 }
Willy Tarreau23677902007-05-08 23:50:35 +02003372 else if (!strcmp(args[1], "smtpchk")) {
3373 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003374 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003375 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003376 curproxy->options2 &= ~PR_O2_CHK_ANY;
3377 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003378
3379 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3380 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3381 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3382 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3383 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3384 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3385 curproxy->check_req = (char *)malloc(reqlen);
3386 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3387 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3388 } else {
3389 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3390 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3391 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3392 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3393 }
3394 }
3395 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003396 else if (!strcmp(args[1], "pgsql-check")) {
3397 /* use PostgreSQL request to check servers' health */
3398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3399 err_code |= ERR_WARN;
3400
3401 free(curproxy->check_req);
3402 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003403 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003404 curproxy->options2 |= PR_O2_PGSQL_CHK;
3405
3406 if (*(args[2])) {
3407 int cur_arg = 2;
3408
3409 while (*(args[cur_arg])) {
3410 if (strcmp(args[cur_arg], "user") == 0) {
3411 char * packet;
3412 uint32_t packet_len;
3413 uint32_t pv;
3414
3415 /* suboption header - needs additional argument for it */
3416 if (*(args[cur_arg+1]) == 0) {
3417 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3418 file, linenum, args[0], args[1], args[cur_arg]);
3419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
3421 }
3422
3423 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3424 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3425 pv = htonl(0x30000); /* protocol version 3.0 */
3426
3427 packet = (char*) calloc(1, packet_len);
3428
3429 memcpy(packet + 4, &pv, 4);
3430
3431 /* copy "user" */
3432 memcpy(packet + 8, "user", 4);
3433
3434 /* copy username */
3435 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3436
3437 free(curproxy->check_req);
3438 curproxy->check_req = packet;
3439 curproxy->check_len = packet_len;
3440
3441 packet_len = htonl(packet_len);
3442 memcpy(packet, &packet_len, 4);
3443 cur_arg += 2;
3444 } else {
3445 /* unknown suboption - catchall */
3446 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3447 file, linenum, args[0], args[1]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
3451 } /* end while loop */
3452 }
3453 }
3454
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003455 else if (!strcmp(args[1], "redis-check")) {
3456 /* use REDIS PING request to check servers' health */
3457 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3458 err_code |= ERR_WARN;
3459
3460 free(curproxy->check_req);
3461 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003462 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003463 curproxy->options2 |= PR_O2_REDIS_CHK;
3464
3465 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3466 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3467 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3468 }
3469
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003470 else if (!strcmp(args[1], "mysql-check")) {
3471 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003472 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3473 err_code |= ERR_WARN;
3474
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003475 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003476 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003477 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003478 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003479
3480 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3481 * const char mysql40_client_auth_pkt[] = {
3482 * "\x0e\x00\x00" // packet length
3483 * "\x01" // packet number
3484 * "\x00\x00" // client capabilities
3485 * "\x00\x00\x01" // max packet
3486 * "haproxy\x00" // username (null terminated string)
3487 * "\x00" // filler (always 0x00)
3488 * "\x01\x00\x00" // packet length
3489 * "\x00" // packet number
3490 * "\x01" // COM_QUIT command
3491 * };
3492 */
3493
3494 if (*(args[2])) {
3495 int cur_arg = 2;
3496
3497 while (*(args[cur_arg])) {
3498 if (strcmp(args[cur_arg], "user") == 0) {
3499 char *mysqluser;
3500 int packetlen, reqlen, userlen;
3501
3502 /* suboption header - needs additional argument for it */
3503 if (*(args[cur_arg+1]) == 0) {
3504 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3505 file, linenum, args[0], args[1], args[cur_arg]);
3506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
3508 }
3509 mysqluser = args[cur_arg + 1];
3510 userlen = strlen(mysqluser);
3511 packetlen = userlen + 7;
3512 reqlen = packetlen + 9;
3513
3514 free(curproxy->check_req);
3515 curproxy->check_req = (char *)calloc(1, reqlen);
3516 curproxy->check_len = reqlen;
3517
3518 snprintf(curproxy->check_req, 4, "%c%c%c",
3519 ((unsigned char) packetlen & 0xff),
3520 ((unsigned char) (packetlen >> 8) & 0xff),
3521 ((unsigned char) (packetlen >> 16) & 0xff));
3522
3523 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003524 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003525 curproxy->check_req[8] = 1;
3526 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3527 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3528 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3529 cur_arg += 2;
3530 } else {
3531 /* unknown suboption - catchall */
3532 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3533 file, linenum, args[0], args[1]);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
3537 } /* end while loop */
3538 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003539 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003540 else if (!strcmp(args[1], "ldap-check")) {
3541 /* use LDAP request to check servers' health */
3542 free(curproxy->check_req);
3543 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003544 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003545 curproxy->options2 |= PR_O2_LDAP_CHK;
3546
3547 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3548 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3549 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3550 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003551 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003552 int cur_arg;
3553
3554 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3555 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003556 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003557
Willy Tarreau87cf5142011-08-19 22:57:24 +02003558 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003559
3560 free(curproxy->fwdfor_hdr_name);
3561 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3562 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3563
3564 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3565 cur_arg = 2;
3566 while (*(args[cur_arg])) {
3567 if (!strcmp(args[cur_arg], "except")) {
3568 /* suboption except - needs additional argument for it */
3569 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3570 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3571 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003572 err_code |= ERR_ALERT | ERR_FATAL;
3573 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003574 }
3575 /* flush useless bits */
3576 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003577 cur_arg += 2;
3578 } else if (!strcmp(args[cur_arg], "header")) {
3579 /* suboption header - needs additional argument for it */
3580 if (*(args[cur_arg+1]) == 0) {
3581 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3582 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003583 err_code |= ERR_ALERT | ERR_FATAL;
3584 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003585 }
3586 free(curproxy->fwdfor_hdr_name);
3587 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3588 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3589 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003590 } else if (!strcmp(args[cur_arg], "if-none")) {
3591 curproxy->options &= ~PR_O_FF_ALWAYS;
3592 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003593 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003594 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003595 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003596 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003599 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003600 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003601 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003602 else if (!strcmp(args[1], "originalto")) {
3603 int cur_arg;
3604
3605 /* insert x-original-to field, but not for the IP address listed as an except.
3606 * set default options (ie: bitfield, header name, etc)
3607 */
3608
3609 curproxy->options |= PR_O_ORGTO;
3610
3611 free(curproxy->orgto_hdr_name);
3612 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3613 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3614
Willy Tarreau87cf5142011-08-19 22:57:24 +02003615 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003616 cur_arg = 2;
3617 while (*(args[cur_arg])) {
3618 if (!strcmp(args[cur_arg], "except")) {
3619 /* suboption except - needs additional argument for it */
3620 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3621 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3622 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003625 }
3626 /* flush useless bits */
3627 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3628 cur_arg += 2;
3629 } else if (!strcmp(args[cur_arg], "header")) {
3630 /* suboption header - needs additional argument for it */
3631 if (*(args[cur_arg+1]) == 0) {
3632 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3633 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003636 }
3637 free(curproxy->orgto_hdr_name);
3638 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3639 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3640 cur_arg += 2;
3641 } else {
3642 /* unknown suboption - catchall */
3643 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3644 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003647 }
3648 } /* end while loop */
3649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 else {
3651 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 }
Willy Tarreau93893792009-07-23 13:19:11 +02003655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003657 else if (!strcmp(args[0], "default_backend")) {
3658 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003660
3661 if (*(args[1]) == 0) {
3662 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003665 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003666 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003667 curproxy->defbe.name = strdup(args[1]);
3668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003669 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003670 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003672
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003673 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 /* enable reconnections to dispatch */
3677 curproxy->options |= PR_O_REDISP;
3678 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003679 else if (!strcmp(args[0], "http-check")) {
3680 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003682
3683 if (strcmp(args[1], "disable-on-404") == 0) {
3684 /* enable a graceful server shutdown on an HTTP 404 response */
3685 curproxy->options |= PR_O_DISABLE404;
3686 }
Willy Tarreauef781042010-01-27 11:53:01 +01003687 else if (strcmp(args[1], "send-state") == 0) {
3688 /* enable emission of the apparent state of a server in HTTP checks */
3689 curproxy->options2 |= PR_O2_CHK_SNDST;
3690 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003691 else if (strcmp(args[1], "expect") == 0) {
3692 const char *ptr_arg;
3693 int cur_arg;
3694
3695 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3696 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
3699 }
3700
3701 cur_arg = 2;
3702 /* consider exclamation marks, sole or at the beginning of a word */
3703 while (*(ptr_arg = args[cur_arg])) {
3704 while (*ptr_arg == '!') {
3705 curproxy->options2 ^= PR_O2_EXP_INV;
3706 ptr_arg++;
3707 }
3708 if (*ptr_arg)
3709 break;
3710 cur_arg++;
3711 }
3712 /* now ptr_arg points to the beginning of a word past any possible
3713 * exclamation mark, and cur_arg is the argument which holds this word.
3714 */
3715 if (strcmp(ptr_arg, "status") == 0) {
3716 if (!*(args[cur_arg + 1])) {
3717 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3718 file, linenum, args[0], args[1], ptr_arg);
3719 err_code |= ERR_ALERT | ERR_FATAL;
3720 goto out;
3721 }
3722 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003723 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003724 curproxy->expect_str = strdup(args[cur_arg + 1]);
3725 }
3726 else if (strcmp(ptr_arg, "string") == 0) {
3727 if (!*(args[cur_arg + 1])) {
3728 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3729 file, linenum, args[0], args[1], ptr_arg);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003734 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003735 curproxy->expect_str = strdup(args[cur_arg + 1]);
3736 }
3737 else if (strcmp(ptr_arg, "rstatus") == 0) {
3738 if (!*(args[cur_arg + 1])) {
3739 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3740 file, linenum, args[0], args[1], ptr_arg);
3741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
3743 }
3744 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003745 free(curproxy->expect_str);
3746 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3747 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003748 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3749 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3750 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3751 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
3754 }
3755 }
3756 else if (strcmp(ptr_arg, "rstring") == 0) {
3757 if (!*(args[cur_arg + 1])) {
3758 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3759 file, linenum, args[0], args[1], ptr_arg);
3760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
3762 }
3763 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003764 free(curproxy->expect_str);
3765 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3766 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003767 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3768 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3769 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3770 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
3774 }
3775 else {
3776 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3777 file, linenum, args[0], args[1], ptr_arg);
3778 err_code |= ERR_ALERT | ERR_FATAL;
3779 goto out;
3780 }
3781 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003782 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003783 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003786 }
3787 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003788 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003789 if (curproxy == &defproxy) {
3790 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003793 }
3794
Willy Tarreaub80c2302007-11-30 20:51:32 +01003795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003797
3798 if (strcmp(args[1], "fail") == 0) {
3799 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003800 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003801 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3802 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003805 }
3806
Willy Tarreauef6494c2010-01-28 17:12:36 +01003807 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003808 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3809 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003812 }
3813 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3814 }
3815 else {
3816 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003819 }
3820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821#ifdef TPROXY
3822 else if (!strcmp(args[0], "transparent")) {
3823 /* enable transparent proxy connections */
3824 curproxy->options |= PR_O_TRANSP;
3825 }
3826#endif
3827 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003828 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
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 (*(args[1]) == 0) {
3832 Alert("parsing [%s:%d] : '%s' expects an integer 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 }
3836 curproxy->maxconn = atol(args[1]);
3837 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003838 else if (!strcmp(args[0], "backlog")) { /* backlog */
3839 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003840 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003841
3842 if (*(args[1]) == 0) {
3843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003846 }
3847 curproxy->backlog = atol(args[1]);
3848 }
Willy Tarreau86034312006-12-29 00:10:33 +01003849 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003852
Willy Tarreau86034312006-12-29 00:10:33 +01003853 if (*(args[1]) == 0) {
3854 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003857 }
3858 curproxy->fullconn = atol(args[1]);
3859 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003860 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3861 if (*(args[1]) == 0) {
3862 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003863 err_code |= ERR_ALERT | ERR_FATAL;
3864 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003866 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3867 if (err) {
3868 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3869 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_ALERT | ERR_FATAL;
3871 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003872 }
3873 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 }
3875 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003876 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003877 if (curproxy == &defproxy) {
3878 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003882 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003884
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 if (strchr(args[1], ':') == NULL) {
3886 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003890 sk = str2sa(args[1]);
3891 if (!sk) {
3892 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
3896 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003897 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 }
3899 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003902
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003903 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003904 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3905 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003908 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003910 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3912 err_code |= ERR_WARN;
3913
3914 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3915 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3916 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3917 }
3918 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3919 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3920 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3921 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003922 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3923 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3924 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3925 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003926 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003927 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
3931 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003932 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003934 char *rport, *raddr;
3935 short realport = 0;
3936 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003937
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003938 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003943 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003944 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003945
3946 if (!*args[2]) {
3947 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003951 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003952
3953 err = invalid_char(args[1]);
3954 if (err) {
3955 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3956 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003959 }
3960
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003961 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01003962 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01003963
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01003964 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
3965 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
3966 err_code |= ERR_ALERT | ERR_ABORT;
3967 goto out;
3968 }
3969
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003970 /* the servers are linked backwards first */
3971 newsrv->next = curproxy->srv;
3972 curproxy->srv = newsrv;
3973 newsrv->proxy = curproxy;
3974 newsrv->conf.file = file;
3975 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976
Simon Hormanaf514952011-06-21 14:34:57 +09003977 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003978 LIST_INIT(&newsrv->pendconns);
3979 do_check = 0;
3980 newsrv->state = SRV_RUNNING; /* early server setup */
3981 newsrv->last_change = now.tv_sec;
3982 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01003985 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003986 * - IP: => port=+0, relative
3987 * - IP:N => port=N, absolute
3988 * - IP:+N => port=+N, relative
3989 * - IP:-N => port=-N, relative
3990 */
3991 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01003992 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003993 if (rport) {
3994 *rport++ = 0;
3995 realport = atol(rport);
3996 if (!isdigit((unsigned char)*rport))
3997 newsrv->state |= SRV_MAPPORTS;
3998 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02003999 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004000
Willy Tarreaufab5a432011-03-04 15:31:53 +01004001 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004002 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004003 if (!sk) {
4004 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
4008 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004009 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004010
4011 newsrv->check_port = curproxy->defsrv.check_port;
4012 newsrv->inter = curproxy->defsrv.inter;
4013 newsrv->fastinter = curproxy->defsrv.fastinter;
4014 newsrv->downinter = curproxy->defsrv.downinter;
4015 newsrv->rise = curproxy->defsrv.rise;
4016 newsrv->fall = curproxy->defsrv.fall;
4017 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4018 newsrv->minconn = curproxy->defsrv.minconn;
4019 newsrv->maxconn = curproxy->defsrv.maxconn;
4020 newsrv->slowstart = curproxy->defsrv.slowstart;
4021 newsrv->onerror = curproxy->defsrv.onerror;
4022 newsrv->consecutive_errors_limit
4023 = curproxy->defsrv.consecutive_errors_limit;
4024 newsrv->uweight = newsrv->iweight
4025 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 newsrv->curfd = -1; /* no health-check in progress */
4028 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004030 cur_arg = 3;
4031 } else {
4032 newsrv = &curproxy->defsrv;
4033 cur_arg = 1;
4034 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004035
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004037 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004038 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004039
4040 if (!*args[cur_arg + 1]) {
4041 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4042 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004045 }
4046
4047 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004048 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004049
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004050 if (newsrv->puid <= 0) {
4051 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004052 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004055 }
4056
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004057 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4058 if (node) {
4059 struct server *target = container_of(node, struct server, conf.id);
4060 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4061 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004066 cur_arg += 2;
4067 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004068 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069 newsrv->cookie = strdup(args[cur_arg + 1]);
4070 newsrv->cklen = strlen(args[cur_arg + 1]);
4071 cur_arg += 2;
4072 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004073 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004074 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4075 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4076 cur_arg += 2;
4077 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004079 if (!*args[cur_arg + 1]) {
4080 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4081 file, linenum, args[cur_arg]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004087 if (newsrv->rise <= 0) {
4088 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4089 file, linenum, args[cur_arg]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093
Willy Tarreau96839092010-03-29 10:02:24 +02004094 if (newsrv->health)
4095 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004096 cur_arg += 2;
4097 }
4098 else if (!strcmp(args[cur_arg], "fall")) {
4099 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004100
4101 if (!*args[cur_arg + 1]) {
4102 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4103 file, linenum, args[cur_arg]);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
4107
4108 if (newsrv->fall <= 0) {
4109 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4110 file, linenum, args[cur_arg]);
4111 err_code |= ERR_ALERT | ERR_FATAL;
4112 goto out;
4113 }
4114
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 cur_arg += 2;
4116 }
4117 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004118 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4119 if (err) {
4120 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4121 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004124 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004125 if (val <= 0) {
4126 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4127 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004130 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004131 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 cur_arg += 2;
4133 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004134 else if (!strcmp(args[cur_arg], "fastinter")) {
4135 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4136 if (err) {
4137 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4138 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004141 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004142 if (val <= 0) {
4143 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4144 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004147 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004148 newsrv->fastinter = val;
4149 cur_arg += 2;
4150 }
4151 else if (!strcmp(args[cur_arg], "downinter")) {
4152 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4153 if (err) {
4154 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4155 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004158 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004159 if (val <= 0) {
4160 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4161 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004164 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004165 newsrv->downinter = val;
4166 cur_arg += 2;
4167 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004168 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004169 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004170 if (!sk) {
4171 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
4174 }
4175 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004176 cur_arg += 2;
4177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 else if (!strcmp(args[cur_arg], "port")) {
4179 newsrv->check_port = atol(args[cur_arg + 1]);
4180 cur_arg += 2;
4181 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004182 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 newsrv->state |= SRV_BACKUP;
4184 cur_arg ++;
4185 }
Simon Hormanfa461682011-06-25 09:39:49 +09004186 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4187 newsrv->state |= SRV_NON_STICK;
4188 cur_arg ++;
4189 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004190 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4191 newsrv->state |= SRV_SEND_PROXY;
4192 cur_arg ++;
4193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004194 else if (!strcmp(args[cur_arg], "weight")) {
4195 int w;
4196 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004197 if (w < 0 || w > 256) {
4198 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004203 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004204 cur_arg += 2;
4205 }
4206 else if (!strcmp(args[cur_arg], "minconn")) {
4207 newsrv->minconn = atol(args[cur_arg + 1]);
4208 cur_arg += 2;
4209 }
4210 else if (!strcmp(args[cur_arg], "maxconn")) {
4211 newsrv->maxconn = atol(args[cur_arg + 1]);
4212 cur_arg += 2;
4213 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004214 else if (!strcmp(args[cur_arg], "maxqueue")) {
4215 newsrv->maxqueue = atol(args[cur_arg + 1]);
4216 cur_arg += 2;
4217 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004218 else if (!strcmp(args[cur_arg], "slowstart")) {
4219 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004220 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004221 if (err) {
4222 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4223 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004226 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004227 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004228 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4229 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004232 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004233 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004234 cur_arg += 2;
4235 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004236 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004237
4238 if (!*args[cur_arg + 1]) {
4239 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4240 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004243 }
4244
4245 newsrv->trackit = strdup(args[cur_arg + 1]);
4246
4247 cur_arg += 2;
4248 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004249 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 global.maxsock++;
4251 do_check = 1;
4252 cur_arg += 1;
4253 }
Willy Tarreau96839092010-03-29 10:02:24 +02004254 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4255 newsrv->state |= SRV_MAINTAIN;
4256 newsrv->state &= ~SRV_RUNNING;
4257 newsrv->health = 0;
4258 cur_arg += 1;
4259 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004260 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004261 if (!strcmp(args[cur_arg + 1], "none"))
4262 newsrv->observe = HANA_OBS_NONE;
4263 else if (!strcmp(args[cur_arg + 1], "layer4"))
4264 newsrv->observe = HANA_OBS_LAYER4;
4265 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4266 if (curproxy->mode != PR_MODE_HTTP) {
4267 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4268 file, linenum, args[cur_arg + 1]);
4269 err_code |= ERR_ALERT;
4270 }
4271 newsrv->observe = HANA_OBS_LAYER7;
4272 }
4273 else {
4274 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004275 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004276 file, linenum, args[cur_arg], args[cur_arg + 1]);
4277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
4280
4281 cur_arg += 2;
4282 }
4283 else if (!strcmp(args[cur_arg], "on-error")) {
4284 if (!strcmp(args[cur_arg + 1], "fastinter"))
4285 newsrv->onerror = HANA_ONERR_FASTINTER;
4286 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4287 newsrv->onerror = HANA_ONERR_FAILCHK;
4288 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4289 newsrv->onerror = HANA_ONERR_SUDDTH;
4290 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4291 newsrv->onerror = HANA_ONERR_MARKDWN;
4292 else {
4293 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004294 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004295 file, linenum, args[cur_arg], args[cur_arg + 1]);
4296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299
4300 cur_arg += 2;
4301 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004302 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4303 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4304 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4305 else {
4306 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4307 file, linenum, args[cur_arg], args[cur_arg + 1]);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311
4312 cur_arg += 2;
4313 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004314 else if (!strcmp(args[cur_arg], "error-limit")) {
4315 if (!*args[cur_arg + 1]) {
4316 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4317 file, linenum, args[cur_arg]);
4318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321
4322 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4323
4324 if (newsrv->consecutive_errors_limit <= 0) {
4325 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4326 file, linenum, args[cur_arg]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004330 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004331 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004332 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004333 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004334 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004335
Willy Tarreaubaaee002006-06-26 02:48:02 +02004336 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004337#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004338 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004339 file, linenum, "source", "usesrc");
4340#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004341 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004342 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004343#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 }
4347 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004348 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4349 if (!sk) {
4350 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004355
4356 if (port_low != port_high) {
4357 int i;
4358 if (port_low <= 0 || port_low > 65535 ||
4359 port_high <= 0 || port_high > 65535 ||
4360 port_low > port_high) {
4361 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4362 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004365 }
4366 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4367 for (i = 0; i < newsrv->sport_range->size; i++)
4368 newsrv->sport_range->ports[i] = port_low + i;
4369 }
4370
Willy Tarreaubaaee002006-06-26 02:48:02 +02004371 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004372 while (*(args[cur_arg])) {
4373 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004374#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4375#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004376 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4377 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4378 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004381 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004382#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004383 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004384 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004385 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004388 }
4389 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004390 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004391 newsrv->state |= SRV_TPROXY_CLI;
4392 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004393 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004394 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004395 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4396 char *name, *end;
4397
4398 name = args[cur_arg+1] + 7;
4399 while (isspace(*name))
4400 name++;
4401
4402 end = name;
4403 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4404 end++;
4405
4406 newsrv->state &= ~SRV_TPROXY_MASK;
4407 newsrv->state |= SRV_TPROXY_DYN;
4408 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4409 newsrv->bind_hdr_len = end - name;
4410 memcpy(newsrv->bind_hdr_name, name, end - name);
4411 newsrv->bind_hdr_name[end-name] = '\0';
4412 newsrv->bind_hdr_occ = -1;
4413
4414 /* now look for an occurrence number */
4415 while (isspace(*end))
4416 end++;
4417 if (*end == ',') {
4418 end++;
4419 name = end;
4420 if (*end == '-')
4421 end++;
4422 while (isdigit(*end))
4423 end++;
4424 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4425 }
4426
4427 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4428 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4429 " occurrences values smaller than %d.\n",
4430 file, linenum, MAX_HDR_HISTORY);
4431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004434 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004435 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004436 if (!sk) {
4437 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
4440 }
4441 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004442 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004443 }
4444 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004445#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004446 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004447#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004448 cur_arg += 2;
4449 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004450#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004451 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004452 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004453 err_code |= ERR_ALERT | ERR_FATAL;
4454 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004455#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4456 } /* "usesrc" */
4457
4458 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4459#ifdef SO_BINDTODEVICE
4460 if (!*args[cur_arg + 1]) {
4461 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4462 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004463 err_code |= ERR_ALERT | ERR_FATAL;
4464 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004465 }
4466 if (newsrv->iface_name)
4467 free(newsrv->iface_name);
4468
4469 newsrv->iface_name = strdup(args[cur_arg + 1]);
4470 newsrv->iface_len = strlen(newsrv->iface_name);
4471 global.last_checks |= LSTCHK_NETADM;
4472#else
4473 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4474 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004475 err_code |= ERR_ALERT | ERR_FATAL;
4476 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004477#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004478 cur_arg += 2;
4479 continue;
4480 }
4481 /* this keyword in not an option of "source" */
4482 break;
4483 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004485 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004486 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4487 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004492 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004493 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004494 file, linenum, newsrv->id);
4495 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004496 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 +01004497 file, linenum);
4498
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004501 }
4502 }
4503
4504 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004505 if (newsrv->trackit) {
4506 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4507 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004510 }
4511
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004512 /* try to get the port from check_addr if check_port not set */
4513 if (!newsrv->check_port)
4514 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004515
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4517 newsrv->check_port = realport; /* by default */
4518 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004519 /* not yet valid, because no port was set on
4520 * the server either. We'll check if we have
4521 * a known port on the first listener.
4522 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004523 struct listener *l = curproxy->listen;
4524 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4525 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004526 }
4527 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004528 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4529 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004533
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004534 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004535 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004536 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4537 err_code |= ERR_ALERT | ERR_ABORT;
4538 goto out;
4539 }
4540
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004541 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 newsrv->state |= SRV_CHECKED;
4543 }
4544
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004545 if (!defsrv) {
4546 if (newsrv->state & SRV_BACKUP)
4547 curproxy->srv_bck++;
4548 else
4549 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004550
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004551 newsrv->prev_state = newsrv->state;
4552 }
William Lallemand723b73a2012-02-08 16:37:49 +01004553 }
4554 else if (strcmp(args[0], "log-format") == 0) {
4555 if (!*(args[1])) {
4556 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
4559 }
4560 parse_logformat_string(args[1], curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004561 }
William Lallemand723b73a2012-02-08 16:37:49 +01004562
William Lallemand0f99e342011-10-12 17:50:54 +02004563 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4564 /* delete previous herited or defined syslog servers */
4565 struct logsrv *back;
4566
4567 if (*(args[1]) != 0) {
4568 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
4571 }
4572
William Lallemand723b73a2012-02-08 16:37:49 +01004573 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4574 LIST_DEL(&tmplogsrv->list);
4575 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004576 }
4577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004579 struct logsrv *logsrv;
4580
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004582 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004583 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004584 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004585 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004586 LIST_INIT(&node->list);
4587 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 }
4590 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004591
4592 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004593
William Lallemand0f99e342011-10-12 17:50:54 +02004594 logsrv->facility = get_log_facility(args[2]);
4595 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599
Willy Tarreaubaaee002006-06-26 02:48:02 +02004600 }
4601
William Lallemand0f99e342011-10-12 17:50:54 +02004602 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004604 logsrv->level = get_log_level(args[3]);
4605 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
4609
Willy Tarreaubaaee002006-06-26 02:48:02 +02004610 }
4611 }
4612
William Lallemand0f99e342011-10-12 17:50:54 +02004613 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004614 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004615 logsrv->minlvl = get_log_level(args[4]);
4616 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004617 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
4620
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004621 }
4622 }
4623
Robert Tsai81ae1952007-12-05 10:47:29 +01004624 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004625 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004626 if (!sk) {
4627 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004628 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
4631 }
William Lallemand0f99e342011-10-12 17:50:54 +02004632 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004633 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004634 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004635 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004636 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
4639 }
William Lallemand0f99e342011-10-12 17:50:54 +02004640 logsrv->addr = *sk;
4641 if (!get_host_port(&logsrv->addr))
4642 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 }
William Lallemand0f99e342011-10-12 17:50:54 +02004644
4645 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004646 }
4647 else {
4648 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4649 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004652 }
4653 }
4654 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004655 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004656 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004657
Willy Tarreau977b8e42006-12-29 14:19:17 +01004658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004660
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004662 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4663 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004667
4668 /* we must first clear any optional default setting */
4669 curproxy->options &= ~PR_O_TPXY_MASK;
4670 free(curproxy->iface_name);
4671 curproxy->iface_name = NULL;
4672 curproxy->iface_len = 0;
4673
Willy Tarreaud5191e72010-02-09 20:50:45 +01004674 sk = str2sa(args[1]);
4675 if (!sk) {
4676 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
4679 }
4680 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004681 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004682
4683 cur_arg = 2;
4684 while (*(args[cur_arg])) {
4685 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004686#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4687#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004688 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4689 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4690 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004693 }
4694#endif
4695 if (!*args[cur_arg + 1]) {
4696 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4697 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004700 }
4701
4702 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004703 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004704 curproxy->options |= PR_O_TPXY_CLI;
4705 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004706 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004707 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004708 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4709 char *name, *end;
4710
4711 name = args[cur_arg+1] + 7;
4712 while (isspace(*name))
4713 name++;
4714
4715 end = name;
4716 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4717 end++;
4718
4719 curproxy->options &= ~PR_O_TPXY_MASK;
4720 curproxy->options |= PR_O_TPXY_DYN;
4721 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4722 curproxy->bind_hdr_len = end - name;
4723 memcpy(curproxy->bind_hdr_name, name, end - name);
4724 curproxy->bind_hdr_name[end-name] = '\0';
4725 curproxy->bind_hdr_occ = -1;
4726
4727 /* now look for an occurrence number */
4728 while (isspace(*end))
4729 end++;
4730 if (*end == ',') {
4731 end++;
4732 name = end;
4733 if (*end == '-')
4734 end++;
4735 while (isdigit(*end))
4736 end++;
4737 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4738 }
4739
4740 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4741 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4742 " occurrences values smaller than %d.\n",
4743 file, linenum, MAX_HDR_HISTORY);
4744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
4746 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004747 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004748 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004749 if (!sk) {
4750 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4751 err_code |= ERR_ALERT | ERR_FATAL;
4752 goto out;
4753 }
4754 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004755 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004756 }
4757 global.last_checks |= LSTCHK_NETADM;
4758#if !defined(CONFIG_HAP_LINUX_TPROXY)
4759 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004760#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004761#else /* no TPROXY support */
4762 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004763 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004766#endif
4767 cur_arg += 2;
4768 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004769 }
4770
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004771 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4772#ifdef SO_BINDTODEVICE
4773 if (!*args[cur_arg + 1]) {
4774 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4775 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004776 err_code |= ERR_ALERT | ERR_FATAL;
4777 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004778 }
4779 if (curproxy->iface_name)
4780 free(curproxy->iface_name);
4781
4782 curproxy->iface_name = strdup(args[cur_arg + 1]);
4783 curproxy->iface_len = strlen(curproxy->iface_name);
4784 global.last_checks |= LSTCHK_NETADM;
4785#else
4786 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4787 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004788 err_code |= ERR_ALERT | ERR_FATAL;
4789 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004790#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004791 cur_arg += 2;
4792 continue;
4793 }
4794 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4795 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004798 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004800 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4801 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4802 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004803 err_code |= ERR_ALERT | ERR_FATAL;
4804 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004805 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
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, 0,
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], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4822 ACL_DIR_REQ, ACT_REMOVE, 0,
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], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4829 ACL_DIR_REQ, ACT_DENY, 0,
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], "reqpass")) { /* 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, 0,
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], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4843 ACL_DIR_REQ, ACT_ALLOW, 0,
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], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004849 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4850 ACL_DIR_REQ, ACT_TARPIT, 0,
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 Tarreaua496b602006-12-17 23:15:24 +01004855 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004856 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4857 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004858 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004859 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004860 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004861 }
4862 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004863 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4864 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004865 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004866 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004867 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004870 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4872 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004876
4877 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4878 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004879 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004880 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 }
4883 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004884 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4885 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004886 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004887 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 }
4890 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004891 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4892 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004893 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004894 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 }
4897 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004898 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4899 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004900 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
4904 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4906 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004907 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004908 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004911 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4913 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004914 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004916 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004918 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004919 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004920
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 if (curproxy == &defproxy) {
4922 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004926 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 if (*(args[1]) == 0) {
4930 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004934
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004935 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4936 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4937 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4938 file, linenum, args[0]);
4939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
4941 }
4942 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4943 }
4944 else if (*args[2]) {
4945 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4946 file, linenum, args[0], args[2]);
4947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
4949 }
4950
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004951 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004952 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004953 wl->s = strdup(args[1]);
4954 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004955 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
4957 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004958 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4960 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004964
Willy Tarreauade5ec42010-01-28 19:33:49 +01004965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4966 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004967 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004970 }
4971 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4973 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004974 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004977 }
4978 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4980 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004981 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004984 }
4985 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004986 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004987 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4988 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 }
4992
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4994 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01004995 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004996 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 }
4999 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5001 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005002 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005003 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 }
5006 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005007 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5008 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005009 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005010 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 }
5013 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005014 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005015
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 if (curproxy == &defproxy) {
5017 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005021 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005022 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 if (*(args[1]) == 0) {
5025 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005026 err_code |= ERR_ALERT | ERR_FATAL;
5027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 }
5029
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005030 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
5031 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5032 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5033 file, linenum, args[0]);
5034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
5036 }
5037 err_code |= warnif_cond_requires_req(cond, file, linenum);
5038 }
5039 else if (*args[2]) {
5040 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5041 file, linenum, args[0], args[2]);
5042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
5044 }
5045
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005046 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005047 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005048 wl->s = strdup(args[1]);
5049 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 }
5051 else if (!strcmp(args[0], "errorloc") ||
5052 !strcmp(args[0], "errorloc302") ||
5053 !strcmp(args[0], "errorloc303")) { /* error location */
5054 int errnum, errlen;
5055 char *err;
5056
Willy Tarreau977b8e42006-12-29 14:19:17 +01005057 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005058 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005059
Willy Tarreaubaaee002006-06-26 02:48:02 +02005060 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005061 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064 }
5065
5066 errnum = atol(args[1]);
5067 if (!strcmp(args[0], "errorloc303")) {
5068 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5069 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5070 } else {
5071 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5072 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5073 }
5074
Willy Tarreau0f772532006-12-23 20:51:41 +01005075 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5076 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005077 chunk_destroy(&curproxy->errmsg[rc]);
5078 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005079 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005081 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005082
5083 if (rc >= HTTP_ERR_SIZE) {
5084 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5085 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 free(err);
5087 }
5088 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005089 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5090 int errnum, errlen, fd;
5091 char *err;
5092 struct stat stat;
5093
5094 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005095 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005096
5097 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005098 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005101 }
5102
5103 fd = open(args[2], O_RDONLY);
5104 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5105 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5106 file, linenum, args[2], args[1]);
5107 if (fd >= 0)
5108 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005109 err_code |= ERR_ALERT | ERR_FATAL;
5110 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005111 }
5112
Willy Tarreau27a674e2009-08-17 07:23:33 +02005113 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005114 errlen = stat.st_size;
5115 } else {
5116 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005117 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005118 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005119 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005120 }
5121
5122 err = malloc(errlen); /* malloc() must succeed during parsing */
5123 errnum = read(fd, err, errlen);
5124 if (errnum != errlen) {
5125 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5126 file, linenum, args[2], args[1]);
5127 close(fd);
5128 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005129 err_code |= ERR_ALERT | ERR_FATAL;
5130 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005131 }
5132 close(fd);
5133
5134 errnum = atol(args[1]);
5135 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5136 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005137 chunk_destroy(&curproxy->errmsg[rc]);
5138 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005139 break;
5140 }
5141 }
5142
5143 if (rc >= HTTP_ERR_SIZE) {
5144 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5145 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005147 free(err);
5148 }
5149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005151 struct cfg_kw_list *kwl;
5152 int index;
5153
5154 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5155 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5156 if (kwl->kw[index].section != CFG_LISTEN)
5157 continue;
5158 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5159 /* prepare error message just in case */
5160 snprintf(trash, sizeof(trash),
5161 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005162 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5163 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005164 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_ALERT | ERR_FATAL;
5166 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005167 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005168 else if (rc > 0) {
5169 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_WARN;
5171 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005172 }
Willy Tarreau93893792009-07-23 13:19:11 +02005173 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005174 }
5175 }
5176 }
5177
Willy Tarreau6daf3432008-01-22 16:44:08 +01005178 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005181 }
Willy Tarreau93893792009-07-23 13:19:11 +02005182 out:
5183 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184}
5185
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005186int
5187cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5188{
5189
5190 int err_code = 0;
5191 const char *err;
5192
5193 if (!strcmp(args[0], "userlist")) { /* new userlist */
5194 struct userlist *newul;
5195
5196 if (!*args[1]) {
5197 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5198 file, linenum, args[0]);
5199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
5201 }
5202
5203 err = invalid_char(args[1]);
5204 if (err) {
5205 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5206 file, linenum, *err, args[0], args[1]);
5207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
5209 }
5210
5211 for (newul = userlist; newul; newul = newul->next)
5212 if (!strcmp(newul->name, args[1])) {
5213 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5214 file, linenum, args[1]);
5215 err_code |= ERR_WARN;
5216 goto out;
5217 }
5218
5219 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5220 if (!newul) {
5221 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5222 err_code |= ERR_ALERT | ERR_ABORT;
5223 goto out;
5224 }
5225
5226 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5227 newul->name = strdup(args[1]);
5228
5229 if (!newul->groupusers | !newul->name) {
5230 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5231 err_code |= ERR_ALERT | ERR_ABORT;
5232 goto out;
5233 }
5234
5235 newul->next = userlist;
5236 userlist = newul;
5237
5238 } else if (!strcmp(args[0], "group")) { /* new group */
5239 int cur_arg, i;
5240 const char *err;
5241
5242 if (!*args[1]) {
5243 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5244 file, linenum, args[0]);
5245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
5247 }
5248
5249 err = invalid_char(args[1]);
5250 if (err) {
5251 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5252 file, linenum, *err, args[0], args[1]);
5253 err_code |= ERR_ALERT | ERR_FATAL;
5254 goto out;
5255 }
5256
5257 for(i = 0; i < userlist->grpcnt; i++)
5258 if (!strcmp(userlist->groups[i], args[1])) {
5259 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5260 file, linenum, args[1], userlist->name);
5261 err_code |= ERR_ALERT;
5262 goto out;
5263 }
5264
5265 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5266 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5267 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271
5272 cur_arg = 2;
5273
5274 while (*args[cur_arg]) {
5275 if (!strcmp(args[cur_arg], "users")) {
5276 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5277 cur_arg += 2;
5278 continue;
5279 } else {
5280 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5281 file, linenum, args[0]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 }
5286
5287 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5288 } else if (!strcmp(args[0], "user")) { /* new user */
5289 struct auth_users *newuser;
5290 int cur_arg;
5291
5292 if (!*args[1]) {
5293 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5294 file, linenum, args[0]);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 }
5298
5299 for (newuser = userlist->users; newuser; newuser = newuser->next)
5300 if (!strcmp(newuser->user, args[1])) {
5301 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5302 file, linenum, args[1], userlist->name);
5303 err_code |= ERR_ALERT;
5304 goto out;
5305 }
5306
5307 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5308 if (!newuser) {
5309 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5310 err_code |= ERR_ALERT | ERR_ABORT;
5311 goto out;
5312 }
5313
5314 newuser->user = strdup(args[1]);
5315
5316 newuser->next = userlist->users;
5317 userlist->users = newuser;
5318
5319 cur_arg = 2;
5320
5321 while (*args[cur_arg]) {
5322 if (!strcmp(args[cur_arg], "password")) {
5323#ifndef CONFIG_HAP_CRYPT
5324 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5325 file, linenum);
5326 err_code |= ERR_ALERT;
5327#endif
5328 newuser->pass = strdup(args[cur_arg + 1]);
5329 cur_arg += 2;
5330 continue;
5331 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5332 newuser->pass = strdup(args[cur_arg + 1]);
5333 newuser->flags |= AU_O_INSECURE;
5334 cur_arg += 2;
5335 continue;
5336 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005337 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005338 cur_arg += 2;
5339 continue;
5340 } else {
5341 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5342 file, linenum, args[0]);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346 }
5347 } else {
5348 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5349 err_code |= ERR_ALERT | ERR_FATAL;
5350 }
5351
5352out:
5353 return err_code;
5354}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355
5356/*
5357 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005358 * Returns the error code, 0 if OK, or any combination of :
5359 * - ERR_ABORT: must abort ASAP
5360 * - ERR_FATAL: we can continue parsing but not start the service
5361 * - ERR_WARN: a warning has been emitted
5362 * - ERR_ALERT: an alert has been emitted
5363 * Only the two first ones can stop processing, the two others are just
5364 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005366int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005368 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005369 FILE *f;
5370 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005372 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 if ((f=fopen(file,"r")) == NULL)
5375 return -1;
5376
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005377 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005378 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005379 char *end;
5380 char *args[MAX_LINE_ARGS + 1];
5381 char *line = thisline;
5382
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 linenum++;
5384
5385 end = line + strlen(line);
5386
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005387 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5388 /* Check if we reached the limit and the last char is not \n.
5389 * Watch out for the last line without the terminating '\n'!
5390 */
5391 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005392 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005393 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005394 }
5395
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005397 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005398 line++;
5399
5400 arg = 0;
5401 args[arg] = line;
5402
5403 while (*line && arg < MAX_LINE_ARGS) {
5404 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5405 * C equivalent value. Other combinations left unchanged (eg: \1).
5406 */
5407 if (*line == '\\') {
5408 int skip = 0;
5409 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5410 *line = line[1];
5411 skip = 1;
5412 }
5413 else if (line[1] == 'r') {
5414 *line = '\r';
5415 skip = 1;
5416 }
5417 else if (line[1] == 'n') {
5418 *line = '\n';
5419 skip = 1;
5420 }
5421 else if (line[1] == 't') {
5422 *line = '\t';
5423 skip = 1;
5424 }
5425 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005426 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 unsigned char hex1, hex2;
5428 hex1 = toupper(line[2]) - '0';
5429 hex2 = toupper(line[3]) - '0';
5430 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5431 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5432 *line = (hex1<<4) + hex2;
5433 skip = 3;
5434 }
5435 else {
5436 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005437 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 }
5439 }
5440 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005441 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 end -= skip;
5443 }
5444 line++;
5445 }
5446 else if (*line == '#' || *line == '\n' || *line == '\r') {
5447 /* end of string, end of loop */
5448 *line = 0;
5449 break;
5450 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005451 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005453 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005454 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 line++;
5456 args[++arg] = line;
5457 }
5458 else {
5459 line++;
5460 }
5461 }
5462
5463 /* empty line */
5464 if (!**args)
5465 continue;
5466
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005467 if (*line) {
5468 /* we had to stop due to too many args.
5469 * Let's terminate the string, print the offending part then cut the
5470 * last arg.
5471 */
5472 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5473 line++;
5474 *line = '\0';
5475
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005476 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005477 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005478 err_code |= ERR_ALERT | ERR_FATAL;
5479 args[arg] = line;
5480 }
5481
Willy Tarreau540abe42007-05-02 20:50:16 +02005482 /* zero out remaining args and ensure that at least one entry
5483 * is zeroed out.
5484 */
5485 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 args[arg] = line;
5487 }
5488
Willy Tarreau3842f002009-06-14 11:39:52 +02005489 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005490 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005491 char *tmp;
5492
Willy Tarreau3842f002009-06-14 11:39:52 +02005493 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005494 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005495 for (arg=0; *args[arg+1]; arg++)
5496 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005497 *tmp = '\0'; // fix the next arg to \0
5498 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005499 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005500 else if (!strcmp(args[0], "default")) {
5501 kwm = KWM_DEF;
5502 for (arg=0; *args[arg+1]; arg++)
5503 args[arg] = args[arg+1]; // shift args after inversion
5504 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005505
William Lallemand0f99e342011-10-12 17:50:54 +02005506 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5507 strcmp(args[0], "log") != 0) {
5508 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005509 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005510 }
5511
Willy Tarreau977b8e42006-12-29 14:19:17 +01005512 if (!strcmp(args[0], "listen") ||
5513 !strcmp(args[0], "frontend") ||
5514 !strcmp(args[0], "backend") ||
5515 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005516 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005518 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005519 cursection = strdup(args[0]);
5520 }
5521 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005523 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005524 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005525 }
5526 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005527 confsect = CFG_USERLIST;
5528 free(cursection);
5529 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005530 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005531 else if (!strcmp(args[0], "peers")) {
5532 confsect = CFG_PEERS;
5533 free(cursection);
5534 cursection = strdup(args[0]);
5535 }
5536
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 /* else it's a section keyword */
5538
5539 switch (confsect) {
5540 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005541 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542 break;
5543 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005544 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005546 case CFG_USERLIST:
5547 err_code |= cfg_parse_users(file, linenum, args, kwm);
5548 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005549 case CFG_PEERS:
5550 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5551 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005553 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005554 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005556
5557 if (err_code & ERR_ABORT)
5558 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005560 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005561 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005563 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005564}
5565
Willy Tarreaubb925012009-07-23 13:36:36 +02005566/*
5567 * Returns the error code, 0 if OK, or any combination of :
5568 * - ERR_ABORT: must abort ASAP
5569 * - ERR_FATAL: we can continue parsing but not start the service
5570 * - ERR_WARN: a warning has been emitted
5571 * - ERR_ALERT: an alert has been emitted
5572 * Only the two first ones can stop processing, the two others are just
5573 * indicators.
5574 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005575int check_config_validity()
5576{
5577 int cfgerr = 0;
5578 struct proxy *curproxy = NULL;
5579 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005580 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005581 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005582 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583
5584 /*
5585 * Now, check for the integrity of all that we have collected.
5586 */
5587
5588 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005589 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005591 /* first, we will invert the proxy list order */
5592 curproxy = NULL;
5593 while (proxy) {
5594 struct proxy *next;
5595
5596 next = proxy->next;
5597 proxy->next = curproxy;
5598 curproxy = proxy;
5599 if (!next)
5600 break;
5601 proxy = next;
5602 }
5603
Willy Tarreaubaaee002006-06-26 02:48:02 +02005604 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005605 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005606 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005607 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005608 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005609 unsigned int next_id;
5610
5611 if (!curproxy->uuid) {
5612 /* proxy ID not set, use automatic numbering with first
5613 * spare entry starting with next_pxid.
5614 */
5615 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5616 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5617 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005618 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005619 next_pxid++;
5620
Willy Tarreau55ea7572007-06-17 19:56:27 +02005621
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005623 /* ensure we don't keep listeners uselessly bound */
5624 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 curproxy = curproxy->next;
5626 continue;
5627 }
5628
Willy Tarreauff01a212009-03-15 13:46:16 +01005629 switch (curproxy->mode) {
5630 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005631 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005632 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005633 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5634 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005635 cfgerr++;
5636 }
5637
5638 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005639 Warning("config : servers will be ignored for %s '%s'.\n",
5640 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005641 break;
5642
5643 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005644 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005645 break;
5646
5647 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005648 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005649 break;
5650 }
5651
5652 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005653 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5654 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 cfgerr++;
5656 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005657
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005658 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005659 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005660 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005661 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5662 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005663 cfgerr++;
5664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005666 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005667 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5668 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005669 cfgerr++;
5670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005672 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005673 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5674 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005675 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005676 }
5677 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005678 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005679 /* If no LB algo is set in a backend, and we're not in
5680 * transparent mode, dispatch mode nor proxy mode, we
5681 * want to use balance roundrobin by default.
5682 */
5683 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5684 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 }
5686 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005687
Willy Tarreau1620ec32011-08-06 17:05:02 +02005688 if (curproxy->options & PR_O_DISPATCH)
5689 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5690 else if (curproxy->options & PR_O_HTTP_PROXY)
5691 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5692 else if (curproxy->options & PR_O_TRANSP)
5693 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005694
Willy Tarreau1620ec32011-08-06 17:05:02 +02005695 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5696 if (curproxy->options & PR_O_DISABLE404) {
5697 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5698 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5699 err_code |= ERR_WARN;
5700 curproxy->options &= ~PR_O_DISABLE404;
5701 }
5702 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5703 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5704 "send-state", proxy_type_str(curproxy), curproxy->id);
5705 err_code |= ERR_WARN;
5706 curproxy->options &= ~PR_O2_CHK_SNDST;
5707 }
Willy Tarreauef781042010-01-27 11:53:01 +01005708 }
5709
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005710 /* if a default backend was specified, let's find it */
5711 if (curproxy->defbe.name) {
5712 struct proxy *target;
5713
Alex Williams96532db2009-11-01 21:27:13 -05005714 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005715 if (!target) {
5716 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5717 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005718 cfgerr++;
5719 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005720 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5721 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005722 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005723 } else {
5724 free(curproxy->defbe.name);
5725 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005726 /* we force the backend to be present on at least all of
5727 * the frontend's processes.
5728 */
5729 target->bind_proc = curproxy->bind_proc ?
5730 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005731
5732 /* Emit a warning if this proxy also has some servers */
5733 if (curproxy->srv) {
5734 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5735 curproxy->id);
5736 err_code |= ERR_WARN;
5737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 }
5739 }
5740
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005741 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005742 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5743 /* map jump target for ACT_SETBE in req_rep chain */
5744 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005745 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005746 struct proxy *target;
5747
Willy Tarreaua496b602006-12-17 23:15:24 +01005748 if (exp->action != ACT_SETBE)
5749 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005750
Alex Williams96532db2009-11-01 21:27:13 -05005751 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005752 if (!target) {
5753 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5754 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005755 cfgerr++;
5756 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005757 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5758 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005759 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005760 } else {
5761 free((void *)exp->replace);
5762 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005763 /* we force the backend to be present on at least all of
5764 * the frontend's processes.
5765 */
5766 target->bind_proc = curproxy->bind_proc ?
5767 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005768 }
5769 }
5770 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005771
5772 /* find the target proxy for 'use_backend' rules */
5773 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005774 struct proxy *target;
5775
Alex Williams96532db2009-11-01 21:27:13 -05005776 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005777
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005778 if (!target) {
5779 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5780 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005781 cfgerr++;
5782 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005783 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5784 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005785 cfgerr++;
5786 } else {
5787 free((void *)rule->be.name);
5788 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005789 /* we force the backend to be present on at least all of
5790 * the frontend's processes.
5791 */
5792 target->bind_proc = curproxy->bind_proc ?
5793 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005794 }
5795 }
5796
Emeric Brunb982a3d2010-01-04 15:45:53 +01005797 /* find the target table for 'stick' rules */
5798 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5799 struct proxy *target;
5800
Emeric Brun1d33b292010-01-04 15:47:17 +01005801 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5802 if (mrule->flags & STK_IS_STORE)
5803 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5804
Emeric Brunb982a3d2010-01-04 15:45:53 +01005805 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005806 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005807 else
5808 target = curproxy;
5809
5810 if (!target) {
5811 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5812 curproxy->id, mrule->table.name);
5813 cfgerr++;
5814 }
5815 else if (target->table.size == 0) {
5816 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5817 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5818 cfgerr++;
5819 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005820 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005821 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5822 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5823 cfgerr++;
5824 }
5825 else {
5826 free((void *)mrule->table.name);
5827 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005828 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005829 }
5830 }
5831
5832 /* find the target table for 'store response' rules */
5833 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5834 struct proxy *target;
5835
Emeric Brun1d33b292010-01-04 15:47:17 +01005836 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5837
Emeric Brunb982a3d2010-01-04 15:45:53 +01005838 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005839 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005840 else
5841 target = curproxy;
5842
5843 if (!target) {
5844 Alert("Proxy '%s': unable to find store table '%s'.\n",
5845 curproxy->id, mrule->table.name);
5846 cfgerr++;
5847 }
5848 else if (target->table.size == 0) {
5849 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5850 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5851 cfgerr++;
5852 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005853 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005854 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5855 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5856 cfgerr++;
5857 }
5858 else {
5859 free((void *)mrule->table.name);
5860 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005861 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005862 }
5863 }
5864
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005865 /* find the target table for 'tcp-request' layer 4 rules */
5866 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5867 struct proxy *target;
5868
Willy Tarreau56123282010-08-06 19:06:56 +02005869 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005870 continue;
5871
5872 if (trule->act_prm.trk_ctr.table.n)
5873 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5874 else
5875 target = curproxy;
5876
5877 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005878 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5879 curproxy->id, trule->act_prm.trk_ctr.table.n,
5880 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005881 cfgerr++;
5882 }
5883 else if (target->table.size == 0) {
5884 Alert("Proxy '%s': table '%s' used but not configured.\n",
5885 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5886 cfgerr++;
5887 }
5888 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005889 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 +02005890 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5891 cfgerr++;
5892 }
5893 else {
5894 free(trule->act_prm.trk_ctr.table.n);
5895 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005896 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005897 * to pass a list of counters to track and allocate them right here using
5898 * stktable_alloc_data_type().
5899 */
5900 }
5901 }
5902
Willy Tarreaud1f96522010-08-03 19:34:32 +02005903 /* find the target table for 'tcp-request' layer 6 rules */
5904 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5905 struct proxy *target;
5906
Willy Tarreau56123282010-08-06 19:06:56 +02005907 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005908 continue;
5909
5910 if (trule->act_prm.trk_ctr.table.n)
5911 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5912 else
5913 target = curproxy;
5914
5915 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005916 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5917 curproxy->id, trule->act_prm.trk_ctr.table.n,
5918 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005919 cfgerr++;
5920 }
5921 else if (target->table.size == 0) {
5922 Alert("Proxy '%s': table '%s' used but not configured.\n",
5923 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5924 cfgerr++;
5925 }
5926 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005927 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 +02005928 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5929 cfgerr++;
5930 }
5931 else {
5932 free(trule->act_prm.trk_ctr.table.n);
5933 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005934 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005935 * to pass a list of counters to track and allocate them right here using
5936 * stktable_alloc_data_type().
5937 */
5938 }
5939 }
5940
Emeric Brun32da3c42010-09-23 18:39:19 +02005941 if (curproxy->table.peers.name) {
5942 struct peers *curpeers = peers;
5943
5944 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
5945 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
5946 free((void *)curproxy->table.peers.name);
5947 curproxy->table.peers.p = peers;
5948 break;
5949 }
5950 }
5951
5952 if (!curpeers) {
5953 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
5954 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005955 free((void *)curproxy->table.peers.name);
5956 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005957 cfgerr++;
5958 }
5959 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02005960 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
5961 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02005962 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02005963 cfgerr++;
5964 }
5965 }
5966
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005967 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01005968 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005969 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
5970 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
5971 "proxy", curproxy->id);
5972 cfgerr++;
5973 goto out_uri_auth_compat;
5974 }
5975
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01005976 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005977 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01005978 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01005979 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005980
Willy Tarreau95fa4692010-02-01 13:05:50 +01005981 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
5982 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005983
5984 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005985 uri_auth_compat_req[i++] = "realm";
5986 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
5987 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005988
Willy Tarreau95fa4692010-02-01 13:05:50 +01005989 uri_auth_compat_req[i++] = "unless";
5990 uri_auth_compat_req[i++] = "{";
5991 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
5992 uri_auth_compat_req[i++] = "}";
5993 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005994
Willy Tarreauff011f22011-01-06 17:51:27 +01005995 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
5996 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01005997 cfgerr++;
5998 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01005999 }
6000
Willy Tarreauff011f22011-01-06 17:51:27 +01006001 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006002
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006003 if (curproxy->uri_auth->auth_realm) {
6004 free(curproxy->uri_auth->auth_realm);
6005 curproxy->uri_auth->auth_realm = NULL;
6006 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006007
6008 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006009 }
6010out_uri_auth_compat:
6011
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006012 cfgerr += acl_find_targets(curproxy);
6013
Willy Tarreau2738a142006-07-08 17:28:09 +02006014 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006015 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006016 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006017 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006018 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006019 " | While not properly invalid, you will certainly encounter various problems\n"
6020 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006021 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006022 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006023 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006024 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006025
Willy Tarreau1fa31262007-12-03 00:36:16 +01006026 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6027 * We must still support older configurations, so let's find out whether those
6028 * parameters have been set or must be copied from contimeouts.
6029 */
6030 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006031 if (!curproxy->timeout.tarpit ||
6032 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006033 /* tarpit timeout not set. We search in the following order:
6034 * default.tarpit, curr.connect, default.connect.
6035 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006036 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006037 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006038 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006039 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006040 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006041 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006042 }
6043 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006044 (!curproxy->timeout.queue ||
6045 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006046 /* queue timeout not set. We search in the following order:
6047 * default.queue, curr.connect, default.connect.
6048 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006049 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006050 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006051 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006052 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006053 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006054 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006055 }
6056 }
6057
Willy Tarreau1620ec32011-08-06 17:05:02 +02006058 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006059 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6060 curproxy->check_req = (char *)malloc(curproxy->check_len);
6061 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006062 }
6063
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006064 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006065 if (curproxy->nb_req_cap) {
6066 if (curproxy->mode == PR_MODE_HTTP) {
6067 curproxy->req_cap_pool = create_pool("ptrcap",
6068 curproxy->nb_req_cap * sizeof(char *),
6069 MEM_F_SHARED);
6070 } else {
6071 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6072 proxy_type_str(curproxy), curproxy->id);
6073 err_code |= ERR_WARN;
6074 curproxy->to_log &= ~LW_REQHDR;
6075 curproxy->nb_req_cap = 0;
6076 }
6077 }
6078
6079 if (curproxy->nb_rsp_cap) {
6080 if (curproxy->mode == PR_MODE_HTTP) {
6081 curproxy->rsp_cap_pool = create_pool("ptrcap",
6082 curproxy->nb_rsp_cap * sizeof(char *),
6083 MEM_F_SHARED);
6084 } else {
6085 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6086 proxy_type_str(curproxy), curproxy->id);
6087 err_code |= ERR_WARN;
6088 curproxy->to_log &= ~LW_REQHDR;
6089 curproxy->nb_rsp_cap = 0;
6090 }
6091 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006092
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093 /* first, we will invert the servers list order */
6094 newsrv = NULL;
6095 while (curproxy->srv) {
6096 struct server *next;
6097
6098 next = curproxy->srv->next;
6099 curproxy->srv->next = newsrv;
6100 newsrv = curproxy->srv;
6101 if (!next)
6102 break;
6103 curproxy->srv = next;
6104 }
6105
Willy Tarreaudd701652010-05-25 23:03:02 +02006106 /* assign automatic UIDs to servers which don't have one yet */
6107 next_id = 1;
6108 newsrv = curproxy->srv;
6109 while (newsrv != NULL) {
6110 if (!newsrv->puid) {
6111 /* server ID not set, use automatic numbering with first
6112 * spare entry starting with next_svid.
6113 */
6114 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6115 newsrv->conf.id.key = newsrv->puid = next_id;
6116 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6117 }
6118 next_id++;
6119 newsrv = newsrv->next;
6120 }
6121
Willy Tarreau20697042007-11-15 23:26:18 +01006122 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006123 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124
Willy Tarreau62c3be22012-01-20 13:12:32 +01006125 /*
6126 * If this server supports a maxconn parameter, it needs a dedicated
6127 * tasks to fill the emptied slots when a connection leaves.
6128 * Also, resolve deferred tracking dependency if needed.
6129 */
6130 newsrv = curproxy->srv;
6131 while (newsrv != NULL) {
6132 if (newsrv->minconn > newsrv->maxconn) {
6133 /* Only 'minconn' was specified, or it was higher than or equal
6134 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6135 * this will avoid further useless expensive computations.
6136 */
6137 newsrv->maxconn = newsrv->minconn;
6138 } else if (newsrv->maxconn && !newsrv->minconn) {
6139 /* minconn was not specified, so we set it to maxconn */
6140 newsrv->minconn = newsrv->maxconn;
6141 }
6142
6143 if (newsrv->trackit) {
6144 struct proxy *px;
6145 struct server *srv;
6146 char *pname, *sname;
6147
6148 pname = newsrv->trackit;
6149 sname = strrchr(pname, '/');
6150
6151 if (sname)
6152 *sname++ = '\0';
6153 else {
6154 sname = pname;
6155 pname = NULL;
6156 }
6157
6158 if (pname) {
6159 px = findproxy(pname, PR_CAP_BE);
6160 if (!px) {
6161 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6162 proxy_type_str(curproxy), curproxy->id,
6163 newsrv->id, pname);
6164 cfgerr++;
6165 goto next_srv;
6166 }
6167 } else
6168 px = curproxy;
6169
6170 srv = findserver(px, sname);
6171 if (!srv) {
6172 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6173 proxy_type_str(curproxy), curproxy->id,
6174 newsrv->id, sname);
6175 cfgerr++;
6176 goto next_srv;
6177 }
6178
6179 if (!(srv->state & SRV_CHECKED)) {
6180 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6181 "tracking as it does not have checks enabled.\n",
6182 proxy_type_str(curproxy), curproxy->id,
6183 newsrv->id, px->id, srv->id);
6184 cfgerr++;
6185 goto next_srv;
6186 }
6187
6188 if (curproxy != px &&
6189 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6190 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6191 "tracking: disable-on-404 option inconsistency.\n",
6192 proxy_type_str(curproxy), curproxy->id,
6193 newsrv->id, px->id, srv->id);
6194 cfgerr++;
6195 goto next_srv;
6196 }
6197
6198 /* if the other server is forced disabled, we have to do the same here */
6199 if (srv->state & SRV_MAINTAIN) {
6200 newsrv->state |= SRV_MAINTAIN;
6201 newsrv->state &= ~SRV_RUNNING;
6202 newsrv->health = 0;
6203 }
6204
6205 newsrv->track = srv;
6206 newsrv->tracknext = srv->tracknext;
6207 srv->tracknext = newsrv;
6208
6209 free(newsrv->trackit);
6210 newsrv->trackit = NULL;
6211 }
6212 next_srv:
6213 newsrv = newsrv->next;
6214 }
6215
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006216 /* We have to initialize the server lookup mechanism depending
6217 * on what LB algorithm was choosen.
6218 */
6219
6220 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6221 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6222 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006223 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6224 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6225 init_server_map(curproxy);
6226 } else {
6227 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6228 fwrr_init_server_groups(curproxy);
6229 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006230 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006231
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006232 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006233 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6234 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6235 fwlc_init_server_tree(curproxy);
6236 } else {
6237 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6238 fas_init_server_tree(curproxy);
6239 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006240 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006241
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006242 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006243 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6244 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6245 chash_init_server_tree(curproxy);
6246 } else {
6247 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6248 init_server_map(curproxy);
6249 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006250 break;
6251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006252
6253 if (curproxy->options & PR_O_LOGASAP)
6254 curproxy->to_log &= ~LW_BYTES;
6255
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006256 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006257 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006258 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6259 proxy_type_str(curproxy), curproxy->id);
6260 err_code |= ERR_WARN;
6261 }
6262
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006263 if (curproxy->mode != PR_MODE_HTTP) {
6264 int optnum;
6265
6266 if (curproxy->options & PR_O_COOK_ANY) {
6267 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6268 proxy_type_str(curproxy), curproxy->id);
6269 err_code |= ERR_WARN;
6270 }
6271
6272 if (curproxy->uri_auth) {
6273 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6274 proxy_type_str(curproxy), curproxy->id);
6275 err_code |= ERR_WARN;
6276 curproxy->uri_auth = NULL;
6277 }
6278
Willy Tarreau87cf5142011-08-19 22:57:24 +02006279 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006280 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6281 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6282 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006283 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006284 }
6285
6286 if (curproxy->options & PR_O_ORGTO) {
6287 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6288 "originalto", proxy_type_str(curproxy), curproxy->id);
6289 err_code |= ERR_WARN;
6290 curproxy->options &= ~PR_O_ORGTO;
6291 }
6292
6293 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6294 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6295 (curproxy->cap & cfg_opts[optnum].cap) &&
6296 (curproxy->options & cfg_opts[optnum].val)) {
6297 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6298 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6299 err_code |= ERR_WARN;
6300 curproxy->options &= ~cfg_opts[optnum].val;
6301 }
6302 }
6303
6304 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6305 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6306 (curproxy->cap & cfg_opts2[optnum].cap) &&
6307 (curproxy->options2 & cfg_opts2[optnum].val)) {
6308 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6309 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6310 err_code |= ERR_WARN;
6311 curproxy->options2 &= ~cfg_opts2[optnum].val;
6312 }
6313 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006314
Willy Tarreauefa5f512010-03-30 20:13:29 +02006315#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006316 if (curproxy->bind_hdr_occ) {
6317 curproxy->bind_hdr_occ = 0;
6318 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6319 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6320 err_code |= ERR_WARN;
6321 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006322#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006323 }
6324
Willy Tarreaubaaee002006-06-26 02:48:02 +02006325 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006326 * ensure that we're not cross-dressing a TCP server into HTTP.
6327 */
6328 newsrv = curproxy->srv;
6329 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006330 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006331 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6332 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006333 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006334 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006335
Willy Tarreau0cec3312011-10-31 13:49:26 +01006336 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6337 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6338 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6339 err_code |= ERR_WARN;
6340 }
6341
Willy Tarreauefa5f512010-03-30 20:13:29 +02006342#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006343 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6344 newsrv->bind_hdr_occ = 0;
6345 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6346 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6347 err_code |= ERR_WARN;
6348 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006349#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006350 newsrv = newsrv->next;
6351 }
6352
Willy Tarreauc1a21672009-08-16 22:37:44 +02006353 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006354 curproxy->accept = frontend_accept;
6355
Willy Tarreauc1a21672009-08-16 22:37:44 +02006356 if (curproxy->tcp_req.inspect_delay ||
6357 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006358 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006359
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006360 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006361 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006362 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006363 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006364
6365 /* both TCP and HTTP must check switching rules */
6366 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6367 }
6368
6369 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006370 if (curproxy->tcp_req.inspect_delay ||
6371 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6372 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6373
Emeric Brun97679e72010-09-23 17:56:44 +02006374 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6375 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6376
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006377 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006378 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006379 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006380 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006381
6382 /* If the backend does requires RDP cookie persistence, we have to
6383 * enable the corresponding analyser.
6384 */
6385 if (curproxy->options2 & PR_O2_RDPC_PRST)
6386 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6387 }
6388
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006389 listener = NULL;
6390 while (curproxy->listen) {
6391 struct listener *next;
6392
6393 next = curproxy->listen->next;
6394 curproxy->listen->next = listener;
6395 listener = curproxy->listen;
6396
6397 if (!next)
6398 break;
6399
6400 curproxy->listen = next;
6401 }
6402
Willy Tarreaue6b98942007-10-29 01:09:36 +01006403 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006404 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006405 listener = curproxy->listen;
6406 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006407 if (!listener->luid) {
6408 /* listener ID not set, use automatic numbering with first
6409 * spare entry starting with next_luid.
6410 */
6411 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6412 listener->conf.id.key = listener->luid = next_id;
6413 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006414 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006415 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006416
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006417 /* enable separate counters */
6418 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6419 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6420 if (!listener->name) {
6421 sprintf(trash, "sock-%d", listener->luid);
6422 listener->name = strdup(trash);
6423 }
6424 }
6425
Willy Tarreaue6b98942007-10-29 01:09:36 +01006426 if (curproxy->options & PR_O_TCP_NOLING)
6427 listener->options |= LI_O_NOLINGER;
6428 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006429 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006430 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006431 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006432 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006433 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006434 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006435
Willy Tarreau8a956912010-10-15 14:27:08 +02006436 if (listener->options & LI_O_ACC_PROXY)
6437 listener->analysers |= AN_REQ_DECODE_PROXY;
6438
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006439 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6440 listener->options |= LI_O_TCP_RULES;
6441
Willy Tarreaude3041d2010-05-31 10:56:17 +02006442 if (curproxy->mon_mask.s_addr)
6443 listener->options |= LI_O_CHK_MONNET;
6444
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006445 /* smart accept mode is automatic in HTTP mode */
6446 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6447 (curproxy->mode == PR_MODE_HTTP &&
6448 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6449 listener->options |= LI_O_NOQUICKACK;
6450
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006451 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006452 listener = listener->next;
6453 }
6454
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006455 /* Check multi-process mode compatibility for the current proxy */
6456 if (global.nbproc > 1) {
6457 int nbproc = 0;
6458 if (curproxy->bind_proc) {
6459 int proc;
6460 for (proc = 0; proc < global.nbproc; proc++) {
6461 if (curproxy->bind_proc & (1 << proc)) {
6462 nbproc++;
6463 }
6464 }
6465 } else {
6466 nbproc = global.nbproc;
6467 }
6468 if (curproxy->table.peers.name) {
6469 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6470 curproxy->id);
6471 cfgerr++;
6472 }
6473 if (nbproc > 1) {
6474 if (curproxy->uri_auth) {
6475 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6476 curproxy->id);
6477 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6478 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6479 curproxy->id);
6480 }
6481 }
6482 if (curproxy->appsession_name) {
6483 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6484 curproxy->id);
6485 }
6486 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6487 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6488 curproxy->id);
6489 }
6490 }
6491 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006492
6493 /* create the task associated with the proxy */
6494 curproxy->task = task_new();
6495 if (curproxy->task) {
6496 curproxy->task->context = curproxy;
6497 curproxy->task->process = manage_proxy;
6498 /* no need to queue, it will be done automatically if some
6499 * listener gets limited.
6500 */
6501 curproxy->task->expire = TICK_ETERNITY;
6502 } else {
6503 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6504 curproxy->id);
6505 cfgerr++;
6506 }
6507
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 curproxy = curproxy->next;
6509 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006510
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006511 /* Check multi-process mode compatibility */
6512 if (global.nbproc > 1) {
6513 if (global.stats_fe) {
6514 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6515 }
6516 }
6517
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006518 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6519 struct auth_users *curuser;
6520 int g;
6521
6522 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6523 unsigned int group_mask = 0;
6524 char *group = NULL;
6525
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006526 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006527 continue;
6528
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006529 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006530
6531 for (g = 0; g < curuserlist->grpcnt; g++)
6532 if (!strcmp(curuserlist->groups[g], group))
6533 break;
6534
6535 if (g == curuserlist->grpcnt) {
6536 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6537 curuserlist->name, group, curuser->user);
6538 err_code |= ERR_ALERT | ERR_FATAL;
6539 goto out;
6540 }
6541
6542 group_mask |= (1 << g);
6543 }
6544
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006545 free(curuser->u.groups);
6546 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006547 }
6548
6549 for (g = 0; g < curuserlist->grpcnt; g++) {
6550 char *user = NULL;
6551
6552 if (!curuserlist->groupusers[g])
6553 continue;
6554
6555 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6556 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6557 if (!strcmp(curuser->user, user))
6558 break;
6559
6560 if (!curuser) {
6561 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6562 curuserlist->name, user, curuserlist->groups[g]);
6563 err_code |= ERR_ALERT | ERR_FATAL;
6564 goto out;
6565 }
6566
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006567 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006568 }
6569
6570 free(curuserlist->groupusers[g]);
6571 }
6572
6573 free(curuserlist->groupusers);
6574
6575#ifdef DEBUG_AUTH
6576 for (g = 0; g < curuserlist->grpcnt; g++) {
6577 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6578
6579 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6580 if (curuser->group_mask & (1 << g))
6581 fprintf(stderr, " %s", curuser->user);
6582 }
6583
6584 fprintf(stderr, "\n");
6585 }
6586#endif
6587
Willy Tarreaufbb78422011-06-05 15:38:35 +02006588 }
6589
6590 /* automatically compute fullconn if not set. We must not do it in the
6591 * loop above because cross-references are not yet fully resolved.
6592 */
6593 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6594 /* If <fullconn> is not set, let's set it to 10% of the sum of
6595 * the possible incoming frontend's maxconns.
6596 */
6597 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6598 struct proxy *fe;
6599 int total = 0;
6600
6601 /* sum up the number of maxconns of frontends which
6602 * reference this backend at least once or which are
6603 * the same one ('listen').
6604 */
6605 for (fe = proxy; fe; fe = fe->next) {
6606 struct switching_rule *rule;
6607 struct hdr_exp *exp;
6608 int found = 0;
6609
6610 if (!(fe->cap & PR_CAP_FE))
6611 continue;
6612
6613 if (fe == curproxy) /* we're on a "listen" instance */
6614 found = 1;
6615
6616 if (fe->defbe.be == curproxy) /* "default_backend" */
6617 found = 1;
6618
6619 /* check if a "use_backend" rule matches */
6620 if (!found) {
6621 list_for_each_entry(rule, &fe->switching_rules, list) {
6622 if (rule->be.backend == curproxy) {
6623 found = 1;
6624 break;
6625 }
6626 }
6627 }
6628
6629 /* check if a "reqsetbe" rule matches */
6630 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6631 if (exp->action == ACT_SETBE &&
6632 (struct proxy *)exp->replace == curproxy) {
6633 found = 1;
6634 break;
6635 }
6636 }
6637
6638 /* now we've checked all possible ways to reference a backend
6639 * from a frontend.
6640 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006641 if (!found)
6642 continue;
6643 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006644 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006645 /* we have the sum of the maxconns in <total>. We only
6646 * keep 10% of that sum to set the default fullconn, with
6647 * a hard minimum of 1 (to avoid a divide by zero).
6648 */
6649 curproxy->fullconn = (total + 9) / 10;
6650 if (!curproxy->fullconn)
6651 curproxy->fullconn = 1;
6652 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006653 }
6654
Willy Tarreau056f5682010-06-06 15:51:11 +02006655 /* initialize stick-tables on backend capable proxies. This must not
6656 * be done earlier because the data size may be discovered while parsing
6657 * other proxies.
6658 */
6659 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006660 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006661
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006662 /*
6663 * Recount currently required checks.
6664 */
6665
6666 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6667 int optnum;
6668
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006669 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6670 if (curproxy->options & cfg_opts[optnum].val)
6671 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006672
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006673 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6674 if (curproxy->options2 & cfg_opts2[optnum].val)
6675 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006676 }
6677
Willy Tarreau122541c2011-09-07 21:24:49 +02006678 if (peers) {
6679 struct peers *curpeers = peers, **last;
6680 struct peer *p, *pb;
6681
6682 /* Remove all peers sections which don't have a valid listener.
6683 * This can happen when a peers section is never referenced and
6684 * does not contain a local peer.
6685 */
6686 last = &peers;
6687 while (*last) {
6688 curpeers = *last;
6689 if (curpeers->peers_fe) {
6690 last = &curpeers->next;
6691 continue;
6692 }
6693
6694 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6695 curpeers->id, localpeer);
6696
6697 p = curpeers->remote;
6698 while (p) {
6699 pb = p->next;
6700 free(p->id);
6701 free(p);
6702 p = pb;
6703 }
6704
6705 /* Destroy and unlink this curpeers section.
6706 * Note: curpeers is backed up into *last.
6707 */
6708 free(curpeers->id);
6709 curpeers = curpeers->next;
6710 free(*last);
6711 *last = curpeers;
6712 }
6713 }
6714
Willy Tarreauac1932d2011-10-24 19:14:41 +02006715 if (!global.tune.max_http_hdr)
6716 global.tune.max_http_hdr = MAX_HTTP_HDR;
6717
Willy Tarreau34eb6712011-10-24 18:15:04 +02006718 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006719 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006720 MEM_F_SHARED);
6721
Willy Tarreaubb925012009-07-23 13:36:36 +02006722 if (cfgerr > 0)
6723 err_code |= ERR_ALERT | ERR_FATAL;
6724 out:
6725 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006726}
6727
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006728/*
6729 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6730 * parsing sessions.
6731 */
6732void cfg_register_keywords(struct cfg_kw_list *kwl)
6733{
6734 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6735}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006736
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006737/*
6738 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6739 */
6740void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6741{
6742 LIST_DEL(&kwl->list);
6743 LIST_INIT(&kwl->list);
6744}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006745
6746/*
6747 * Local variables:
6748 * c-indent-level: 8
6749 * c-basic-offset: 8
6750 * End:
6751 */