blob: d827d4c0fbb7a4168ea6feaf72c084cf3c1e8e36 [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 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002705 else if (strcmp(args[0], "use-server") == 0) {
2706 struct server_rule *rule;
2707
2708 if (curproxy == &defproxy) {
2709 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
2712 }
2713
2714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2715 err_code |= ERR_WARN;
2716
2717 if (*(args[1]) == 0) {
2718 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
2722
2723 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2724 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2725 file, linenum, args[0]);
2726 err_code |= ERR_ALERT | ERR_FATAL;
2727 goto out;
2728 }
2729
2730 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2731 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
2732 file, linenum);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736
2737 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2738
2739 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2740 rule->cond = cond;
2741 rule->srv.name = strdup(args[1]);
2742 LIST_INIT(&rule->list);
2743 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2744 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2745 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002746 else if ((!strcmp(args[0], "force-persist")) ||
2747 (!strcmp(args[0], "ignore-persist"))) {
2748 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002749
2750 if (curproxy == &defproxy) {
2751 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
2755
2756 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2757 err_code |= ERR_WARN;
2758
Willy Tarreauef6494c2010-01-28 17:12:36 +01002759 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002760 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2761 file, linenum, args[0]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
Willy Tarreauef6494c2010-01-28 17:12:36 +01002766 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002767 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2768 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002773 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002774
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002775 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002776 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002777 if (!strcmp(args[0], "force-persist")) {
2778 rule->type = PERSIST_TYPE_FORCE;
2779 } else {
2780 rule->type = PERSIST_TYPE_IGNORE;
2781 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002782 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002783 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002784 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002785 else if (!strcmp(args[0], "stick-table")) {
2786 int myidx = 1;
2787
Emeric Brun32da3c42010-09-23 18:39:19 +02002788 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002789 curproxy->table.type = (unsigned int)-1;
2790 while (*args[myidx]) {
2791 const char *err;
2792
2793 if (strcmp(args[myidx], "size") == 0) {
2794 myidx++;
2795 if (!*(args[myidx])) {
2796 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2797 file, linenum, args[myidx-1]);
2798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
2800 }
2801 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2802 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2803 file, linenum, *err, args[myidx-1]);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002807 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002808 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002809 else if (strcmp(args[myidx], "peers") == 0) {
2810 myidx++;
2811 if (!*(args[myidx])) {
2812 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2813 file, linenum, args[myidx-1]);
2814 err_code |= ERR_ALERT | ERR_FATAL;
2815 goto out;
2816 }
2817 curproxy->table.peers.name = strdup(args[myidx++]);
2818 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002819 else if (strcmp(args[myidx], "expire") == 0) {
2820 myidx++;
2821 if (!*(args[myidx])) {
2822 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2823 file, linenum, args[myidx-1]);
2824 err_code |= ERR_ALERT | ERR_FATAL;
2825 goto out;
2826 }
2827 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2828 if (err) {
2829 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2830 file, linenum, *err, args[myidx-1]);
2831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
2833 }
2834 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002835 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002836 }
2837 else if (strcmp(args[myidx], "nopurge") == 0) {
2838 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002839 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002840 }
2841 else if (strcmp(args[myidx], "type") == 0) {
2842 myidx++;
2843 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2844 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2845 file, linenum, args[myidx]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002849 /* myidx already points to next arg */
2850 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002851 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002852 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002853 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002854
2855 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002856 nw = args[myidx];
2857 while (*nw) {
2858 /* the "store" keyword supports a comma-separated list */
2859 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002860 sa = NULL; /* store arg */
2861 while (*nw && *nw != ',') {
2862 if (*nw == '(') {
2863 *nw = 0;
2864 sa = ++nw;
2865 while (*nw != ')') {
2866 if (!*nw) {
2867 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2868 file, linenum, args[0], cw);
2869 err_code |= ERR_ALERT | ERR_FATAL;
2870 goto out;
2871 }
2872 nw++;
2873 }
2874 *nw = '\0';
2875 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002876 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002877 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002878 if (*nw)
2879 *nw++ = '\0';
2880 type = stktable_get_data_type(cw);
2881 if (type < 0) {
2882 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2883 file, linenum, args[0], cw);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
Willy Tarreauac782882010-06-20 10:41:54 +02002887
2888 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2889 switch (err) {
2890 case PE_NONE: break;
2891 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002892 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2893 file, linenum, args[0], cw);
2894 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002895 break;
2896
2897 case PE_ARG_MISSING:
2898 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2899 file, linenum, args[0], cw);
2900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
2902
2903 case PE_ARG_NOT_USED:
2904 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2905 file, linenum, args[0], cw);
2906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
2908
2909 default:
2910 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2911 file, linenum, args[0], cw);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002914 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002915 }
2916 myidx++;
2917 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002918 else {
2919 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2920 file, linenum, args[myidx]);
2921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002923 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002924 }
2925
2926 if (!curproxy->table.size) {
2927 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2928 file, linenum);
2929 err_code |= ERR_ALERT | ERR_FATAL;
2930 goto out;
2931 }
2932
2933 if (curproxy->table.type == (unsigned int)-1) {
2934 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2935 file, linenum);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
2939 }
2940 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 struct sticking_rule *rule;
2942 struct pattern_expr *expr;
2943 int myidx = 0;
2944 const char *name = NULL;
2945 int flags;
2946
2947 if (curproxy == &defproxy) {
2948 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
2953 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2954 err_code |= ERR_WARN;
2955 goto out;
2956 }
2957
2958 myidx++;
2959 if ((strcmp(args[myidx], "store") == 0) ||
2960 (strcmp(args[myidx], "store-request") == 0)) {
2961 myidx++;
2962 flags = STK_IS_STORE;
2963 }
2964 else if (strcmp(args[myidx], "store-response") == 0) {
2965 myidx++;
2966 flags = STK_IS_STORE | STK_ON_RSP;
2967 }
2968 else if (strcmp(args[myidx], "match") == 0) {
2969 myidx++;
2970 flags = STK_IS_MATCH;
2971 }
2972 else if (strcmp(args[myidx], "on") == 0) {
2973 myidx++;
2974 flags = STK_IS_MATCH | STK_IS_STORE;
2975 }
2976 else {
2977 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981
2982 if (*(args[myidx]) == 0) {
2983 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
Emeric Brun485479d2010-09-23 18:02:19 +02002988 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01002989 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02002990 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
2993 }
2994
2995 if (flags & STK_ON_RSP) {
2996 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2997 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2998 file, linenum, args[0], expr->fetch->kw);
2999 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003000 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003001 goto out;
3002 }
3003 } else {
3004 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
3005 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3006 file, linenum, args[0], expr->fetch->kw);
3007 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003008 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003009 goto out;
3010 }
3011 }
3012
3013 if (strcmp(args[myidx], "table") == 0) {
3014 myidx++;
3015 name = args[myidx++];
3016 }
3017
Willy Tarreauef6494c2010-01-28 17:12:36 +01003018 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
3019 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
3021 file, linenum, args[0]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003023 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003024 goto out;
3025 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003026 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003027 else if (*(args[myidx])) {
3028 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3029 file, linenum, args[0], args[myidx]);
3030 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003031 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003032 goto out;
3033 }
Emeric Brun97679e72010-09-23 17:56:44 +02003034 if (flags & STK_ON_RSP)
3035 err_code |= warnif_cond_requires_req(cond, file, linenum);
3036 else
3037 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003038
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3040 rule->cond = cond;
3041 rule->expr = expr;
3042 rule->flags = flags;
3043 rule->table.name = name ? strdup(name) : NULL;
3044 LIST_INIT(&rule->list);
3045 if (flags & STK_ON_RSP)
3046 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3047 else
3048 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3049 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003051 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003052 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003053
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3055 curproxy->uri_auth = NULL; /* we must detach from the default config */
3056
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003057 if (!*args[1]) {
3058 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003059 } else if (!strcmp(args[1], "admin")) {
3060 struct stats_admin_rule *rule;
3061
3062 if (curproxy == &defproxy) {
3063 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066 }
3067
3068 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3069 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3070 err_code |= ERR_ALERT | ERR_ABORT;
3071 goto out;
3072 }
3073
3074 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3075 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3076 file, linenum, args[0], args[1]);
3077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
3079 }
3080 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3081 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3082 file, linenum, args[0], args[1]);
3083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
3085 }
3086
3087 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3088
3089 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3090 rule->cond = cond;
3091 LIST_INIT(&rule->list);
3092 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 } else if (!strcmp(args[1], "uri")) {
3094 if (*(args[2]) == 0) {
3095 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3099 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_ABORT;
3101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003102 }
3103 } else if (!strcmp(args[1], "realm")) {
3104 if (*(args[2]) == 0) {
3105 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3109 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003110 err_code |= ERR_ALERT | ERR_ABORT;
3111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003113 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003114 unsigned interval;
3115
3116 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3117 if (err) {
3118 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3119 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003122 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3123 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_ABORT;
3125 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003126 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003127 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003128 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003129
3130 if (curproxy == &defproxy) {
3131 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
3134 }
3135
3136 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3137 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3138 err_code |= ERR_ALERT | ERR_ABORT;
3139 goto out;
3140 }
3141
Willy Tarreauff011f22011-01-06 17:51:27 +01003142 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3143 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003144 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3145 file, linenum, args[0]);
3146 err_code |= ERR_WARN;
3147 }
3148
Willy Tarreauff011f22011-01-06 17:51:27 +01003149 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003150
Willy Tarreauff011f22011-01-06 17:51:27 +01003151 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003152 err_code |= ERR_ALERT | ERR_ABORT;
3153 goto out;
3154 }
3155
Willy Tarreauff011f22011-01-06 17:51:27 +01003156 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3157 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003158
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 } else if (!strcmp(args[1], "auth")) {
3160 if (*(args[2]) == 0) {
3161 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3165 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003166 err_code |= ERR_ALERT | ERR_ABORT;
3167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003168 }
3169 } else if (!strcmp(args[1], "scope")) {
3170 if (*(args[2]) == 0) {
3171 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003172 err_code |= ERR_ALERT | ERR_FATAL;
3173 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3175 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003176 err_code |= ERR_ALERT | ERR_ABORT;
3177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
3179 } else if (!strcmp(args[1], "enable")) {
3180 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3181 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_ALERT | ERR_ABORT;
3183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003185 } else if (!strcmp(args[1], "hide-version")) {
3186 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3187 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_ABORT;
3189 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003190 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003191 } else if (!strcmp(args[1], "show-legends")) {
3192 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3193 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3194 err_code |= ERR_ALERT | ERR_ABORT;
3195 goto out;
3196 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003197 } else if (!strcmp(args[1], "show-node")) {
3198
3199 if (*args[2]) {
3200 int i;
3201 char c;
3202
3203 for (i=0; args[2][i]; i++) {
3204 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003205 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3206 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003207 break;
3208 }
3209
3210 if (!i || args[2][i]) {
3211 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3212 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3213 file, linenum, args[0], args[1]);
3214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
3216 }
3217 }
3218
3219 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3220 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3221 err_code |= ERR_ALERT | ERR_ABORT;
3222 goto out;
3223 }
3224 } else if (!strcmp(args[1], "show-desc")) {
3225 char *desc = NULL;
3226
3227 if (*args[2]) {
3228 int i, len=0;
3229 char *d;
3230
3231 for(i=2; *args[i]; i++)
3232 len += strlen(args[i])+1;
3233
3234 desc = d = (char *)calloc(1, len);
3235
3236 d += sprintf(d, "%s", args[2]);
3237 for(i=3; *args[i]; i++)
3238 d += sprintf(d, " %s", args[i]);
3239 }
3240
3241 if (!*args[2] && !global.desc)
3242 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3243 file, linenum, args[1]);
3244 else {
3245 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3246 free(desc);
3247 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3248 err_code |= ERR_ALERT | ERR_ABORT;
3249 goto out;
3250 }
3251 free(desc);
3252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003254stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003255 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 +01003256 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259 }
3260 }
3261 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003262 int optnum;
3263
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003264 if (*(args[1]) == '\0') {
3265 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3266 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003267 err_code |= ERR_ALERT | ERR_FATAL;
3268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003270
3271 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3272 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003273 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3274 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3275 file, linenum, cfg_opts[optnum].name);
3276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278 }
Willy Tarreau93893792009-07-23 13:19:11 +02003279 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3280 err_code |= ERR_WARN;
3281 goto out;
3282 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003283
Willy Tarreau3842f002009-06-14 11:39:52 +02003284 curproxy->no_options &= ~cfg_opts[optnum].val;
3285 curproxy->options &= ~cfg_opts[optnum].val;
3286
3287 switch (kwm) {
3288 case KWM_STD:
3289 curproxy->options |= cfg_opts[optnum].val;
3290 break;
3291 case KWM_NO:
3292 curproxy->no_options |= cfg_opts[optnum].val;
3293 break;
3294 case KWM_DEF: /* already cleared */
3295 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003296 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003297
Willy Tarreau93893792009-07-23 13:19:11 +02003298 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003299 }
3300 }
3301
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003302 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3303 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003304 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3305 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3306 file, linenum, cfg_opts2[optnum].name);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
Willy Tarreau93893792009-07-23 13:19:11 +02003310 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3311 err_code |= ERR_WARN;
3312 goto out;
3313 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003314
Willy Tarreau3842f002009-06-14 11:39:52 +02003315 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3316 curproxy->options2 &= ~cfg_opts2[optnum].val;
3317
3318 switch (kwm) {
3319 case KWM_STD:
3320 curproxy->options2 |= cfg_opts2[optnum].val;
3321 break;
3322 case KWM_NO:
3323 curproxy->no_options2 |= cfg_opts2[optnum].val;
3324 break;
3325 case KWM_DEF: /* already cleared */
3326 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003327 }
Willy Tarreau93893792009-07-23 13:19:11 +02003328 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003329 }
3330 }
3331
Willy Tarreau3842f002009-06-14 11:39:52 +02003332 if (kwm != KWM_STD) {
3333 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003334 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_FATAL;
3336 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003337 }
3338
Emeric Brun3a058f32009-06-30 18:26:00 +02003339 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003340 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02003342 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
William Lallemand723b73a2012-02-08 16:37:49 +01003344 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003345 if (*(args[2]) != '\0') {
3346 if (!strcmp(args[2], "clf")) {
3347 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003348 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003349 } else {
3350 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003353 }
3354 }
William Lallemand723b73a2012-02-08 16:37:49 +01003355 parse_logformat_string(logformat, curproxy);
Emeric Brun3a058f32009-06-30 18:26:00 +02003356 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003357 else if (!strcmp(args[1], "tcplog")) {
3358 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 /* generate a detailed TCP log */
3360 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003361 logformat = default_tcp_log_format;
3362 parse_logformat_string(logformat, curproxy);
3363 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 else if (!strcmp(args[1], "tcpka")) {
3365 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003366 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003367 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003368
3369 if (curproxy->cap & PR_CAP_FE)
3370 curproxy->options |= PR_O_TCP_CLI_KA;
3371 if (curproxy->cap & PR_CAP_BE)
3372 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 }
3374 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003375 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_WARN;
3377
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003379 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003380 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003381 curproxy->options2 &= ~PR_O2_CHK_ANY;
3382 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 if (!*args[2]) { /* no argument */
3384 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3385 curproxy->check_len = strlen(DEF_CHECK_REQ);
3386 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003387 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 curproxy->check_req = (char *)malloc(reqlen);
3389 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003390 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003392 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 if (*args[4])
3394 reqlen += strlen(args[4]);
3395 else
3396 reqlen += strlen("HTTP/1.0");
3397
3398 curproxy->check_req = (char *)malloc(reqlen);
3399 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003400 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003402 }
3403 else if (!strcmp(args[1], "ssl-hello-chk")) {
3404 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003405 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003407
Willy Tarreaua534fea2008-08-03 12:19:50 +02003408 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003409 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003410 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003411 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
Willy Tarreau23677902007-05-08 23:50:35 +02003413 else if (!strcmp(args[1], "smtpchk")) {
3414 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003415 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003416 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003417 curproxy->options2 &= ~PR_O2_CHK_ANY;
3418 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003419
3420 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3421 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3422 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3423 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3424 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3425 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3426 curproxy->check_req = (char *)malloc(reqlen);
3427 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3428 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3429 } else {
3430 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3431 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3432 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3433 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3434 }
3435 }
3436 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003437 else if (!strcmp(args[1], "pgsql-check")) {
3438 /* use PostgreSQL request to check servers' health */
3439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3440 err_code |= ERR_WARN;
3441
3442 free(curproxy->check_req);
3443 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003444 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003445 curproxy->options2 |= PR_O2_PGSQL_CHK;
3446
3447 if (*(args[2])) {
3448 int cur_arg = 2;
3449
3450 while (*(args[cur_arg])) {
3451 if (strcmp(args[cur_arg], "user") == 0) {
3452 char * packet;
3453 uint32_t packet_len;
3454 uint32_t pv;
3455
3456 /* suboption header - needs additional argument for it */
3457 if (*(args[cur_arg+1]) == 0) {
3458 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3459 file, linenum, args[0], args[1], args[cur_arg]);
3460 err_code |= ERR_ALERT | ERR_FATAL;
3461 goto out;
3462 }
3463
3464 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3465 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3466 pv = htonl(0x30000); /* protocol version 3.0 */
3467
3468 packet = (char*) calloc(1, packet_len);
3469
3470 memcpy(packet + 4, &pv, 4);
3471
3472 /* copy "user" */
3473 memcpy(packet + 8, "user", 4);
3474
3475 /* copy username */
3476 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3477
3478 free(curproxy->check_req);
3479 curproxy->check_req = packet;
3480 curproxy->check_len = packet_len;
3481
3482 packet_len = htonl(packet_len);
3483 memcpy(packet, &packet_len, 4);
3484 cur_arg += 2;
3485 } else {
3486 /* unknown suboption - catchall */
3487 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3488 file, linenum, args[0], args[1]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492 } /* end while loop */
3493 }
3494 }
3495
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003496 else if (!strcmp(args[1], "redis-check")) {
3497 /* use REDIS PING request to check servers' health */
3498 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3499 err_code |= ERR_WARN;
3500
3501 free(curproxy->check_req);
3502 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003503 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003504 curproxy->options2 |= PR_O2_REDIS_CHK;
3505
3506 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3507 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3508 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3509 }
3510
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003511 else if (!strcmp(args[1], "mysql-check")) {
3512 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3514 err_code |= ERR_WARN;
3515
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003516 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003517 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003518 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003519 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003520
3521 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3522 * const char mysql40_client_auth_pkt[] = {
3523 * "\x0e\x00\x00" // packet length
3524 * "\x01" // packet number
3525 * "\x00\x00" // client capabilities
3526 * "\x00\x00\x01" // max packet
3527 * "haproxy\x00" // username (null terminated string)
3528 * "\x00" // filler (always 0x00)
3529 * "\x01\x00\x00" // packet length
3530 * "\x00" // packet number
3531 * "\x01" // COM_QUIT command
3532 * };
3533 */
3534
3535 if (*(args[2])) {
3536 int cur_arg = 2;
3537
3538 while (*(args[cur_arg])) {
3539 if (strcmp(args[cur_arg], "user") == 0) {
3540 char *mysqluser;
3541 int packetlen, reqlen, userlen;
3542
3543 /* suboption header - needs additional argument for it */
3544 if (*(args[cur_arg+1]) == 0) {
3545 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3546 file, linenum, args[0], args[1], args[cur_arg]);
3547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
3549 }
3550 mysqluser = args[cur_arg + 1];
3551 userlen = strlen(mysqluser);
3552 packetlen = userlen + 7;
3553 reqlen = packetlen + 9;
3554
3555 free(curproxy->check_req);
3556 curproxy->check_req = (char *)calloc(1, reqlen);
3557 curproxy->check_len = reqlen;
3558
3559 snprintf(curproxy->check_req, 4, "%c%c%c",
3560 ((unsigned char) packetlen & 0xff),
3561 ((unsigned char) (packetlen >> 8) & 0xff),
3562 ((unsigned char) (packetlen >> 16) & 0xff));
3563
3564 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003565 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003566 curproxy->check_req[8] = 1;
3567 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3568 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3569 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3570 cur_arg += 2;
3571 } else {
3572 /* unknown suboption - catchall */
3573 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3574 file, linenum, args[0], args[1]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578 } /* end while loop */
3579 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003580 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003581 else if (!strcmp(args[1], "ldap-check")) {
3582 /* use LDAP request to check servers' health */
3583 free(curproxy->check_req);
3584 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003585 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003586 curproxy->options2 |= PR_O2_LDAP_CHK;
3587
3588 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3589 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3590 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3591 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003592 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003593 int cur_arg;
3594
3595 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3596 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003597 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003598
Willy Tarreau87cf5142011-08-19 22:57:24 +02003599 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003600
3601 free(curproxy->fwdfor_hdr_name);
3602 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3603 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3604
3605 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3606 cur_arg = 2;
3607 while (*(args[cur_arg])) {
3608 if (!strcmp(args[cur_arg], "except")) {
3609 /* suboption except - needs additional argument for it */
3610 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3611 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3612 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003615 }
3616 /* flush useless bits */
3617 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003618 cur_arg += 2;
3619 } else if (!strcmp(args[cur_arg], "header")) {
3620 /* suboption header - needs additional argument for it */
3621 if (*(args[cur_arg+1]) == 0) {
3622 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3623 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003626 }
3627 free(curproxy->fwdfor_hdr_name);
3628 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3629 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3630 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003631 } else if (!strcmp(args[cur_arg], "if-none")) {
3632 curproxy->options &= ~PR_O_FF_ALWAYS;
3633 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003634 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003635 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003636 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003637 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003638 err_code |= ERR_ALERT | ERR_FATAL;
3639 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003640 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003641 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003642 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003643 else if (!strcmp(args[1], "originalto")) {
3644 int cur_arg;
3645
3646 /* insert x-original-to field, but not for the IP address listed as an except.
3647 * set default options (ie: bitfield, header name, etc)
3648 */
3649
3650 curproxy->options |= PR_O_ORGTO;
3651
3652 free(curproxy->orgto_hdr_name);
3653 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3654 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3655
Willy Tarreau87cf5142011-08-19 22:57:24 +02003656 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003657 cur_arg = 2;
3658 while (*(args[cur_arg])) {
3659 if (!strcmp(args[cur_arg], "except")) {
3660 /* suboption except - needs additional argument for it */
3661 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3662 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3663 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003666 }
3667 /* flush useless bits */
3668 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3669 cur_arg += 2;
3670 } else if (!strcmp(args[cur_arg], "header")) {
3671 /* suboption header - needs additional argument for it */
3672 if (*(args[cur_arg+1]) == 0) {
3673 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3674 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003675 err_code |= ERR_ALERT | ERR_FATAL;
3676 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003677 }
3678 free(curproxy->orgto_hdr_name);
3679 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3680 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3681 cur_arg += 2;
3682 } else {
3683 /* unknown suboption - catchall */
3684 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3685 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003688 }
3689 } /* end while loop */
3690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003691 else {
3692 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003693 err_code |= ERR_ALERT | ERR_FATAL;
3694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 }
Willy Tarreau93893792009-07-23 13:19:11 +02003696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003698 else if (!strcmp(args[0], "default_backend")) {
3699 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003701
3702 if (*(args[1]) == 0) {
3703 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003706 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003707 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003708 curproxy->defbe.name = strdup(args[1]);
3709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003710 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003711 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003712 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003713
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003714 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 /* enable reconnections to dispatch */
3718 curproxy->options |= PR_O_REDISP;
3719 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003720 else if (!strcmp(args[0], "http-check")) {
3721 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003723
3724 if (strcmp(args[1], "disable-on-404") == 0) {
3725 /* enable a graceful server shutdown on an HTTP 404 response */
3726 curproxy->options |= PR_O_DISABLE404;
3727 }
Willy Tarreauef781042010-01-27 11:53:01 +01003728 else if (strcmp(args[1], "send-state") == 0) {
3729 /* enable emission of the apparent state of a server in HTTP checks */
3730 curproxy->options2 |= PR_O2_CHK_SNDST;
3731 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003732 else if (strcmp(args[1], "expect") == 0) {
3733 const char *ptr_arg;
3734 int cur_arg;
3735
3736 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3737 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
3740 }
3741
3742 cur_arg = 2;
3743 /* consider exclamation marks, sole or at the beginning of a word */
3744 while (*(ptr_arg = args[cur_arg])) {
3745 while (*ptr_arg == '!') {
3746 curproxy->options2 ^= PR_O2_EXP_INV;
3747 ptr_arg++;
3748 }
3749 if (*ptr_arg)
3750 break;
3751 cur_arg++;
3752 }
3753 /* now ptr_arg points to the beginning of a word past any possible
3754 * exclamation mark, and cur_arg is the argument which holds this word.
3755 */
3756 if (strcmp(ptr_arg, "status") == 0) {
3757 if (!*(args[cur_arg + 1])) {
3758 Alert("parsing [%s:%d] : '%s %s %s' expects <string> 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_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003764 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003765 curproxy->expect_str = strdup(args[cur_arg + 1]);
3766 }
3767 else if (strcmp(ptr_arg, "string") == 0) {
3768 if (!*(args[cur_arg + 1])) {
3769 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3770 file, linenum, args[0], args[1], ptr_arg);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
3774 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003775 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003776 curproxy->expect_str = strdup(args[cur_arg + 1]);
3777 }
3778 else if (strcmp(ptr_arg, "rstatus") == 0) {
3779 if (!*(args[cur_arg + 1])) {
3780 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3781 file, linenum, args[0], args[1], ptr_arg);
3782 err_code |= ERR_ALERT | ERR_FATAL;
3783 goto out;
3784 }
3785 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003786 free(curproxy->expect_str);
3787 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3788 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003789 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3790 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3791 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3792 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796 }
3797 else if (strcmp(ptr_arg, "rstring") == 0) {
3798 if (!*(args[cur_arg + 1])) {
3799 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3800 file, linenum, args[0], args[1], ptr_arg);
3801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
3803 }
3804 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003805 free(curproxy->expect_str);
3806 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3807 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003808 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3809 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3810 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3811 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
3814 }
3815 }
3816 else {
3817 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3818 file, linenum, args[0], args[1], ptr_arg);
3819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
3821 }
3822 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003823 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003824 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 +02003825 err_code |= ERR_ALERT | ERR_FATAL;
3826 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003827 }
3828 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003829 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003830 if (curproxy == &defproxy) {
3831 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003834 }
3835
Willy Tarreaub80c2302007-11-30 20:51:32 +01003836 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003837 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003838
3839 if (strcmp(args[1], "fail") == 0) {
3840 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003841 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003842 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3843 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003846 }
3847
Willy Tarreauef6494c2010-01-28 17:12:36 +01003848 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003849 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3850 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003853 }
3854 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3855 }
3856 else {
3857 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003860 }
3861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862#ifdef TPROXY
3863 else if (!strcmp(args[0], "transparent")) {
3864 /* enable transparent proxy connections */
3865 curproxy->options |= PR_O_TRANSP;
3866 }
3867#endif
3868 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003869 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003870 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003871
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 if (*(args[1]) == 0) {
3873 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
3877 curproxy->maxconn = atol(args[1]);
3878 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003879 else if (!strcmp(args[0], "backlog")) { /* backlog */
3880 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003882
3883 if (*(args[1]) == 0) {
3884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003887 }
3888 curproxy->backlog = atol(args[1]);
3889 }
Willy Tarreau86034312006-12-29 00:10:33 +01003890 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003891 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003893
Willy Tarreau86034312006-12-29 00:10:33 +01003894 if (*(args[1]) == 0) {
3895 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003898 }
3899 curproxy->fullconn = atol(args[1]);
3900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003901 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3902 if (*(args[1]) == 0) {
3903 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003906 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003907 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3908 if (err) {
3909 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3910 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003913 }
3914 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 }
3916 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003917 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918 if (curproxy == &defproxy) {
3919 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003922 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003923 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003925
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 if (strchr(args[1], ':') == NULL) {
3927 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003931 sk = str2sa(args[1]);
3932 if (!sk) {
3933 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
3936 }
3937 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003938 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
3940 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003941 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003943
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003944 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003945 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3946 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003951 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3952 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3953 err_code |= ERR_WARN;
3954
3955 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3956 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3957 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3958 }
3959 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3960 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3961 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3962 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003963 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3964 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3965 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3966 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003967 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003968 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003969 err_code |= ERR_ALERT | ERR_FATAL;
3970 goto out;
3971 }
3972 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003973 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003974 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003975 char *rport, *raddr;
3976 short realport = 0;
3977 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003979 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003980 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003984 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986
3987 if (!*args[2]) {
3988 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3989 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003993
3994 err = invalid_char(args[1]);
3995 if (err) {
3996 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
3997 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004000 }
4001
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004002 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004003 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004004
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004005 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4006 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4007 err_code |= ERR_ALERT | ERR_ABORT;
4008 goto out;
4009 }
4010
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004011 /* the servers are linked backwards first */
4012 newsrv->next = curproxy->srv;
4013 curproxy->srv = newsrv;
4014 newsrv->proxy = curproxy;
4015 newsrv->conf.file = file;
4016 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017
Simon Hormanaf514952011-06-21 14:34:57 +09004018 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004019 LIST_INIT(&newsrv->pendconns);
4020 do_check = 0;
4021 newsrv->state = SRV_RUNNING; /* early server setup */
4022 newsrv->last_change = now.tv_sec;
4023 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004026 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004027 * - IP: => port=+0, relative
4028 * - IP:N => port=N, absolute
4029 * - IP:+N => port=+N, relative
4030 * - IP:-N => port=-N, relative
4031 */
4032 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004033 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004034 if (rport) {
4035 *rport++ = 0;
4036 realport = atol(rport);
4037 if (!isdigit((unsigned char)*rport))
4038 newsrv->state |= SRV_MAPPORTS;
4039 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004040 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004041
Willy Tarreaufab5a432011-03-04 15:31:53 +01004042 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004043 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004044 if (!sk) {
4045 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004050 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004051
4052 newsrv->check_port = curproxy->defsrv.check_port;
4053 newsrv->inter = curproxy->defsrv.inter;
4054 newsrv->fastinter = curproxy->defsrv.fastinter;
4055 newsrv->downinter = curproxy->defsrv.downinter;
4056 newsrv->rise = curproxy->defsrv.rise;
4057 newsrv->fall = curproxy->defsrv.fall;
4058 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4059 newsrv->minconn = curproxy->defsrv.minconn;
4060 newsrv->maxconn = curproxy->defsrv.maxconn;
4061 newsrv->slowstart = curproxy->defsrv.slowstart;
4062 newsrv->onerror = curproxy->defsrv.onerror;
4063 newsrv->consecutive_errors_limit
4064 = curproxy->defsrv.consecutive_errors_limit;
4065 newsrv->uweight = newsrv->iweight
4066 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004068 newsrv->curfd = -1; /* no health-check in progress */
4069 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004071 cur_arg = 3;
4072 } else {
4073 newsrv = &curproxy->defsrv;
4074 cur_arg = 1;
4075 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004076
Willy Tarreaubaaee002006-06-26 02:48:02 +02004077 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004078 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004079 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004080
4081 if (!*args[cur_arg + 1]) {
4082 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4083 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004086 }
4087
4088 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004089 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004090
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004091 if (newsrv->puid <= 0) {
4092 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004093 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004096 }
4097
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004098 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4099 if (node) {
4100 struct server *target = container_of(node, struct server, conf.id);
4101 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4102 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004107 cur_arg += 2;
4108 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004109 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 newsrv->cookie = strdup(args[cur_arg + 1]);
4111 newsrv->cklen = strlen(args[cur_arg + 1]);
4112 cur_arg += 2;
4113 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004114 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004115 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4116 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4117 cur_arg += 2;
4118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004120 if (!*args[cur_arg + 1]) {
4121 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4122 file, linenum, args[cur_arg]);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
4125 }
4126
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004128 if (newsrv->rise <= 0) {
4129 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4130 file, linenum, args[cur_arg]);
4131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
4133 }
4134
Willy Tarreau96839092010-03-29 10:02:24 +02004135 if (newsrv->health)
4136 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 cur_arg += 2;
4138 }
4139 else if (!strcmp(args[cur_arg], "fall")) {
4140 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004141
4142 if (!*args[cur_arg + 1]) {
4143 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4144 file, linenum, args[cur_arg]);
4145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
4147 }
4148
4149 if (newsrv->fall <= 0) {
4150 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4151 file, linenum, args[cur_arg]);
4152 err_code |= ERR_ALERT | ERR_FATAL;
4153 goto out;
4154 }
4155
Willy Tarreaubaaee002006-06-26 02:48:02 +02004156 cur_arg += 2;
4157 }
4158 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004159 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4160 if (err) {
4161 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4162 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004163 err_code |= ERR_ALERT | ERR_FATAL;
4164 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004165 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004166 if (val <= 0) {
4167 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4168 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004171 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004172 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173 cur_arg += 2;
4174 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004175 else if (!strcmp(args[cur_arg], "fastinter")) {
4176 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4177 if (err) {
4178 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4179 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004182 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004183 if (val <= 0) {
4184 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4185 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004188 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004189 newsrv->fastinter = val;
4190 cur_arg += 2;
4191 }
4192 else if (!strcmp(args[cur_arg], "downinter")) {
4193 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4194 if (err) {
4195 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4196 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004199 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004200 if (val <= 0) {
4201 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4202 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004205 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004206 newsrv->downinter = val;
4207 cur_arg += 2;
4208 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004209 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004210 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004211 if (!sk) {
4212 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4213 err_code |= ERR_ALERT | ERR_FATAL;
4214 goto out;
4215 }
4216 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004217 cur_arg += 2;
4218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 else if (!strcmp(args[cur_arg], "port")) {
4220 newsrv->check_port = atol(args[cur_arg + 1]);
4221 cur_arg += 2;
4222 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004223 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 newsrv->state |= SRV_BACKUP;
4225 cur_arg ++;
4226 }
Simon Hormanfa461682011-06-25 09:39:49 +09004227 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4228 newsrv->state |= SRV_NON_STICK;
4229 cur_arg ++;
4230 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004231 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4232 newsrv->state |= SRV_SEND_PROXY;
4233 cur_arg ++;
4234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 else if (!strcmp(args[cur_arg], "weight")) {
4236 int w;
4237 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004238 if (w < 0 || w > 256) {
4239 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004240 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004243 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004244 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004245 cur_arg += 2;
4246 }
4247 else if (!strcmp(args[cur_arg], "minconn")) {
4248 newsrv->minconn = atol(args[cur_arg + 1]);
4249 cur_arg += 2;
4250 }
4251 else if (!strcmp(args[cur_arg], "maxconn")) {
4252 newsrv->maxconn = atol(args[cur_arg + 1]);
4253 cur_arg += 2;
4254 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004255 else if (!strcmp(args[cur_arg], "maxqueue")) {
4256 newsrv->maxqueue = atol(args[cur_arg + 1]);
4257 cur_arg += 2;
4258 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004259 else if (!strcmp(args[cur_arg], "slowstart")) {
4260 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004261 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004262 if (err) {
4263 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4264 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004267 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004268 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004269 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4270 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004273 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004274 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004275 cur_arg += 2;
4276 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004277 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004278
4279 if (!*args[cur_arg + 1]) {
4280 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4281 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_ALERT | ERR_FATAL;
4283 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004284 }
4285
4286 newsrv->trackit = strdup(args[cur_arg + 1]);
4287
4288 cur_arg += 2;
4289 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004290 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004291 global.maxsock++;
4292 do_check = 1;
4293 cur_arg += 1;
4294 }
Willy Tarreau96839092010-03-29 10:02:24 +02004295 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4296 newsrv->state |= SRV_MAINTAIN;
4297 newsrv->state &= ~SRV_RUNNING;
4298 newsrv->health = 0;
4299 cur_arg += 1;
4300 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004301 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004302 if (!strcmp(args[cur_arg + 1], "none"))
4303 newsrv->observe = HANA_OBS_NONE;
4304 else if (!strcmp(args[cur_arg + 1], "layer4"))
4305 newsrv->observe = HANA_OBS_LAYER4;
4306 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4307 if (curproxy->mode != PR_MODE_HTTP) {
4308 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4309 file, linenum, args[cur_arg + 1]);
4310 err_code |= ERR_ALERT;
4311 }
4312 newsrv->observe = HANA_OBS_LAYER7;
4313 }
4314 else {
4315 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004316 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004317 file, linenum, args[cur_arg], args[cur_arg + 1]);
4318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
4320 }
4321
4322 cur_arg += 2;
4323 }
4324 else if (!strcmp(args[cur_arg], "on-error")) {
4325 if (!strcmp(args[cur_arg + 1], "fastinter"))
4326 newsrv->onerror = HANA_ONERR_FASTINTER;
4327 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4328 newsrv->onerror = HANA_ONERR_FAILCHK;
4329 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4330 newsrv->onerror = HANA_ONERR_SUDDTH;
4331 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4332 newsrv->onerror = HANA_ONERR_MARKDWN;
4333 else {
4334 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004335 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004336 file, linenum, args[cur_arg], args[cur_arg + 1]);
4337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
4339 }
4340
4341 cur_arg += 2;
4342 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004343 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4344 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4345 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4346 else {
4347 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4348 file, linenum, args[cur_arg], args[cur_arg + 1]);
4349 err_code |= ERR_ALERT | ERR_FATAL;
4350 goto out;
4351 }
4352
4353 cur_arg += 2;
4354 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004355 else if (!strcmp(args[cur_arg], "error-limit")) {
4356 if (!*args[cur_arg + 1]) {
4357 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4358 file, linenum, args[cur_arg]);
4359 err_code |= ERR_ALERT | ERR_FATAL;
4360 goto out;
4361 }
4362
4363 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4364
4365 if (newsrv->consecutive_errors_limit <= 0) {
4366 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4367 file, linenum, args[cur_arg]);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004371 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004372 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004373 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004374 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004375 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004376
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004378#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004379 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004380 file, linenum, "source", "usesrc");
4381#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004382 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004384#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004385 err_code |= ERR_ALERT | ERR_FATAL;
4386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004387 }
4388 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004389 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4390 if (!sk) {
4391 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004396
4397 if (port_low != port_high) {
4398 int i;
4399 if (port_low <= 0 || port_low > 65535 ||
4400 port_high <= 0 || port_high > 65535 ||
4401 port_low > port_high) {
4402 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4403 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004406 }
4407 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4408 for (i = 0; i < newsrv->sport_range->size; i++)
4409 newsrv->sport_range->ports[i] = port_low + i;
4410 }
4411
Willy Tarreaubaaee002006-06-26 02:48:02 +02004412 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004413 while (*(args[cur_arg])) {
4414 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004415#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4416#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004417 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4418 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4419 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004422 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004423#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004424 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004425 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004429 }
4430 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004431 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004432 newsrv->state |= SRV_TPROXY_CLI;
4433 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004434 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004436 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4437 char *name, *end;
4438
4439 name = args[cur_arg+1] + 7;
4440 while (isspace(*name))
4441 name++;
4442
4443 end = name;
4444 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4445 end++;
4446
4447 newsrv->state &= ~SRV_TPROXY_MASK;
4448 newsrv->state |= SRV_TPROXY_DYN;
4449 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4450 newsrv->bind_hdr_len = end - name;
4451 memcpy(newsrv->bind_hdr_name, name, end - name);
4452 newsrv->bind_hdr_name[end-name] = '\0';
4453 newsrv->bind_hdr_occ = -1;
4454
4455 /* now look for an occurrence number */
4456 while (isspace(*end))
4457 end++;
4458 if (*end == ',') {
4459 end++;
4460 name = end;
4461 if (*end == '-')
4462 end++;
4463 while (isdigit(*end))
4464 end++;
4465 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4466 }
4467
4468 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4469 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4470 " occurrences values smaller than %d.\n",
4471 file, linenum, MAX_HDR_HISTORY);
4472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
4474 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004475 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004476 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004477 if (!sk) {
4478 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
4481 }
4482 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004483 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004484 }
4485 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004486#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004487 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004488#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004489 cur_arg += 2;
4490 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004491#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004492 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004493 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004494 err_code |= ERR_ALERT | ERR_FATAL;
4495 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004496#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4497 } /* "usesrc" */
4498
4499 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4500#ifdef SO_BINDTODEVICE
4501 if (!*args[cur_arg + 1]) {
4502 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4503 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004506 }
4507 if (newsrv->iface_name)
4508 free(newsrv->iface_name);
4509
4510 newsrv->iface_name = strdup(args[cur_arg + 1]);
4511 newsrv->iface_len = strlen(newsrv->iface_name);
4512 global.last_checks |= LSTCHK_NETADM;
4513#else
4514 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4515 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004518#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004519 cur_arg += 2;
4520 continue;
4521 }
4522 /* this keyword in not an option of "source" */
4523 break;
4524 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004526 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004527 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4528 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004531 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004533 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004534 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 +01004535 file, linenum, newsrv->id);
4536 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004537 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 +01004538 file, linenum);
4539
Willy Tarreau93893792009-07-23 13:19:11 +02004540 err_code |= ERR_ALERT | ERR_FATAL;
4541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004542 }
4543 }
4544
4545 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004546 if (newsrv->trackit) {
4547 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4548 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004549 err_code |= ERR_ALERT | ERR_FATAL;
4550 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004551 }
4552
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004553 /* try to get the port from check_addr if check_port not set */
4554 if (!newsrv->check_port)
4555 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004556
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4558 newsrv->check_port = realport; /* by default */
4559 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004560 /* not yet valid, because no port was set on
4561 * the server either. We'll check if we have
4562 * a known port on the first listener.
4563 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004564 struct listener *l = curproxy->listen;
4565 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4566 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004567 }
4568 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4570 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004574
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004575 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004576 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004577 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4578 err_code |= ERR_ALERT | ERR_ABORT;
4579 goto out;
4580 }
4581
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004582 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 newsrv->state |= SRV_CHECKED;
4584 }
4585
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004586 if (!defsrv) {
4587 if (newsrv->state & SRV_BACKUP)
4588 curproxy->srv_bck++;
4589 else
4590 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004591
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004592 newsrv->prev_state = newsrv->state;
4593 }
William Lallemand723b73a2012-02-08 16:37:49 +01004594 }
4595 else if (strcmp(args[0], "log-format") == 0) {
4596 if (!*(args[1])) {
4597 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
4600 }
4601 parse_logformat_string(args[1], curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004602 }
William Lallemand723b73a2012-02-08 16:37:49 +01004603
William Lallemand0f99e342011-10-12 17:50:54 +02004604 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4605 /* delete previous herited or defined syslog servers */
4606 struct logsrv *back;
4607
4608 if (*(args[1]) != 0) {
4609 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
4613
William Lallemand723b73a2012-02-08 16:37:49 +01004614 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4615 LIST_DEL(&tmplogsrv->list);
4616 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004617 }
4618 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004620 struct logsrv *logsrv;
4621
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004623 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004624 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004625 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004626 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004627 LIST_INIT(&node->list);
4628 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004630 }
4631 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004632
4633 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004634
William Lallemand0f99e342011-10-12 17:50:54 +02004635 logsrv->facility = get_log_facility(args[2]);
4636 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004637 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
4640
Willy Tarreaubaaee002006-06-26 02:48:02 +02004641 }
4642
William Lallemand0f99e342011-10-12 17:50:54 +02004643 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004644 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004645 logsrv->level = get_log_level(args[3]);
4646 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
4650
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 }
4652 }
4653
William Lallemand0f99e342011-10-12 17:50:54 +02004654 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004655 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004656 logsrv->minlvl = get_log_level(args[4]);
4657 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004658 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
4661
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004662 }
4663 }
4664
Robert Tsai81ae1952007-12-05 10:47:29 +01004665 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004666 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004667 if (!sk) {
4668 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004669 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004670 err_code |= ERR_ALERT | ERR_FATAL;
4671 goto out;
4672 }
William Lallemand0f99e342011-10-12 17:50:54 +02004673 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004674 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004675 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004676 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004677 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
4680 }
William Lallemand0f99e342011-10-12 17:50:54 +02004681 logsrv->addr = *sk;
4682 if (!get_host_port(&logsrv->addr))
4683 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 }
William Lallemand0f99e342011-10-12 17:50:54 +02004685
4686 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004687 }
4688 else {
4689 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4690 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004691 err_code |= ERR_ALERT | ERR_FATAL;
4692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693 }
4694 }
4695 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004696 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004697 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004698
Willy Tarreau977b8e42006-12-29 14:19:17 +01004699 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004700 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004701
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004703 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4704 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004705 err_code |= ERR_ALERT | ERR_FATAL;
4706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004707 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004708
4709 /* we must first clear any optional default setting */
4710 curproxy->options &= ~PR_O_TPXY_MASK;
4711 free(curproxy->iface_name);
4712 curproxy->iface_name = NULL;
4713 curproxy->iface_len = 0;
4714
Willy Tarreaud5191e72010-02-09 20:50:45 +01004715 sk = str2sa(args[1]);
4716 if (!sk) {
4717 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4718 err_code |= ERR_ALERT | ERR_FATAL;
4719 goto out;
4720 }
4721 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004723
4724 cur_arg = 2;
4725 while (*(args[cur_arg])) {
4726 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004727#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4728#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004729 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4730 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4731 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004734 }
4735#endif
4736 if (!*args[cur_arg + 1]) {
4737 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4738 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004739 err_code |= ERR_ALERT | ERR_FATAL;
4740 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004741 }
4742
4743 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004744 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004745 curproxy->options |= PR_O_TPXY_CLI;
4746 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004747 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004748 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004749 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4750 char *name, *end;
4751
4752 name = args[cur_arg+1] + 7;
4753 while (isspace(*name))
4754 name++;
4755
4756 end = name;
4757 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4758 end++;
4759
4760 curproxy->options &= ~PR_O_TPXY_MASK;
4761 curproxy->options |= PR_O_TPXY_DYN;
4762 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4763 curproxy->bind_hdr_len = end - name;
4764 memcpy(curproxy->bind_hdr_name, name, end - name);
4765 curproxy->bind_hdr_name[end-name] = '\0';
4766 curproxy->bind_hdr_occ = -1;
4767
4768 /* now look for an occurrence number */
4769 while (isspace(*end))
4770 end++;
4771 if (*end == ',') {
4772 end++;
4773 name = end;
4774 if (*end == '-')
4775 end++;
4776 while (isdigit(*end))
4777 end++;
4778 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4779 }
4780
4781 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4782 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4783 " occurrences values smaller than %d.\n",
4784 file, linenum, MAX_HDR_HISTORY);
4785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
4787 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004788 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004789 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004790 if (!sk) {
4791 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
4795 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004796 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004797 }
4798 global.last_checks |= LSTCHK_NETADM;
4799#if !defined(CONFIG_HAP_LINUX_TPROXY)
4800 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004801#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004802#else /* no TPROXY support */
4803 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004804 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004807#endif
4808 cur_arg += 2;
4809 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004810 }
4811
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004812 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4813#ifdef SO_BINDTODEVICE
4814 if (!*args[cur_arg + 1]) {
4815 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4816 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004819 }
4820 if (curproxy->iface_name)
4821 free(curproxy->iface_name);
4822
4823 curproxy->iface_name = strdup(args[cur_arg + 1]);
4824 curproxy->iface_len = strlen(curproxy->iface_name);
4825 global.last_checks |= LSTCHK_NETADM;
4826#else
4827 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4828 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004831#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004832 cur_arg += 2;
4833 continue;
4834 }
4835 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4836 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004837 err_code |= ERR_ALERT | ERR_FATAL;
4838 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004841 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4842 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4843 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004848 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004849 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4850 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004854
4855 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4856 ACL_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004857 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004858 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004859 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 }
4861 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004862 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4863 ACL_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004864 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004865 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004867 }
4868 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004869 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4870 ACL_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004871 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004872 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 }
4875 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004876 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4877 ACL_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004878 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004879 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004880 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 }
4882 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004883 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4884 ACL_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004885 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004886 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004888 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004889 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004890 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4891 ACL_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004892 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004893 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004894 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004895 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004896 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004897 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4898 ACL_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004899 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004900 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004901 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004902 }
4903 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004904 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4905 ACL_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004906 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004907 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004908 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004911 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4913 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004917
4918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4919 ACL_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004920 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 }
4924 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4926 ACL_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004927 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4933 ACL_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004934 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004937 }
4938 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4940 ACL_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004944 }
4945 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4947 ACL_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004948 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004952 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
4954 ACL_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004955 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004957 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004960 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004961
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 if (curproxy == &defproxy) {
4963 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004967 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969
Willy Tarreaubaaee002006-06-26 02:48:02 +02004970 if (*(args[1]) == 0) {
4971 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004975
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004976 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
4977 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
4978 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
4979 file, linenum, args[0]);
4980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
4982 }
4983 err_code |= warnif_cond_requires_resp(cond, file, linenum);
4984 }
4985 else if (*args[2]) {
4986 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
4987 file, linenum, args[0], args[2]);
4988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
4990 }
4991
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004992 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01004993 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004994 wl->s = strdup(args[1]);
4995 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02004996 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
4998 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004999 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5001 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005004 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005005
Willy Tarreauade5ec42010-01-28 19:33:49 +01005006 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5007 ACL_DIR_RTR, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005008 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005009 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005011 }
5012 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005013 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5014 ACL_DIR_RTR, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005015 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005016 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005018 }
5019 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005020 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5021 ACL_DIR_RTR, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005022 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005023 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 }
5026 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005027 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5029 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005030 err_code |= ERR_ALERT | ERR_FATAL;
5031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005032 }
5033
Willy Tarreauade5ec42010-01-28 19:33:49 +01005034 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5035 ACL_DIR_RTR, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005036 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005037 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 }
5040 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005041 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5042 ACL_DIR_RTR, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005043 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005044 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
5047 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005048 err_code |= create_cond_regex_rule(file, linenum, curproxy,
5049 ACL_DIR_RTR, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005050 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005051 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 }
5054 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005055 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005056
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 if (curproxy == &defproxy) {
5058 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005062 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005063 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005064
Willy Tarreaubaaee002006-06-26 02:48:02 +02005065 if (*(args[1]) == 0) {
5066 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005067 err_code |= ERR_ALERT | ERR_FATAL;
5068 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069 }
5070
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005071 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
5072 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5073 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5074 file, linenum, args[0]);
5075 err_code |= ERR_ALERT | ERR_FATAL;
5076 goto out;
5077 }
5078 err_code |= warnif_cond_requires_req(cond, file, linenum);
5079 }
5080 else if (*args[2]) {
5081 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5082 file, linenum, args[0], args[2]);
5083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
5085 }
5086
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005087 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005088 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005089 wl->s = strdup(args[1]);
5090 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005091 }
5092 else if (!strcmp(args[0], "errorloc") ||
5093 !strcmp(args[0], "errorloc302") ||
5094 !strcmp(args[0], "errorloc303")) { /* error location */
5095 int errnum, errlen;
5096 char *err;
5097
Willy Tarreau977b8e42006-12-29 14:19:17 +01005098 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005099 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005100
Willy Tarreaubaaee002006-06-26 02:48:02 +02005101 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005102 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005105 }
5106
5107 errnum = atol(args[1]);
5108 if (!strcmp(args[0], "errorloc303")) {
5109 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5110 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5111 } else {
5112 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5113 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5114 }
5115
Willy Tarreau0f772532006-12-23 20:51:41 +01005116 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5117 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005118 chunk_destroy(&curproxy->errmsg[rc]);
5119 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005120 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005122 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005123
5124 if (rc >= HTTP_ERR_SIZE) {
5125 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5126 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005127 free(err);
5128 }
5129 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005130 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5131 int errnum, errlen, fd;
5132 char *err;
5133 struct stat stat;
5134
5135 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005137
5138 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005139 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005140 err_code |= ERR_ALERT | ERR_FATAL;
5141 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005142 }
5143
5144 fd = open(args[2], O_RDONLY);
5145 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5146 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5147 file, linenum, args[2], args[1]);
5148 if (fd >= 0)
5149 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005152 }
5153
Willy Tarreau27a674e2009-08-17 07:23:33 +02005154 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005155 errlen = stat.st_size;
5156 } else {
5157 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005158 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005160 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005161 }
5162
5163 err = malloc(errlen); /* malloc() must succeed during parsing */
5164 errnum = read(fd, err, errlen);
5165 if (errnum != errlen) {
5166 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5167 file, linenum, args[2], args[1]);
5168 close(fd);
5169 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005170 err_code |= ERR_ALERT | ERR_FATAL;
5171 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005172 }
5173 close(fd);
5174
5175 errnum = atol(args[1]);
5176 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5177 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005178 chunk_destroy(&curproxy->errmsg[rc]);
5179 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005180 break;
5181 }
5182 }
5183
5184 if (rc >= HTTP_ERR_SIZE) {
5185 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5186 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005188 free(err);
5189 }
5190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005192 struct cfg_kw_list *kwl;
5193 int index;
5194
5195 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5196 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5197 if (kwl->kw[index].section != CFG_LISTEN)
5198 continue;
5199 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5200 /* prepare error message just in case */
5201 snprintf(trash, sizeof(trash),
5202 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005203 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5204 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005205 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005208 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005209 else if (rc > 0) {
5210 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_WARN;
5212 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005213 }
Willy Tarreau93893792009-07-23 13:19:11 +02005214 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005215 }
5216 }
5217 }
5218
Willy Tarreau6daf3432008-01-22 16:44:08 +01005219 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
Willy Tarreau93893792009-07-23 13:19:11 +02005223 out:
5224 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225}
5226
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005227int
5228cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5229{
5230
5231 int err_code = 0;
5232 const char *err;
5233
5234 if (!strcmp(args[0], "userlist")) { /* new userlist */
5235 struct userlist *newul;
5236
5237 if (!*args[1]) {
5238 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5239 file, linenum, args[0]);
5240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
5242 }
5243
5244 err = invalid_char(args[1]);
5245 if (err) {
5246 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5247 file, linenum, *err, args[0], args[1]);
5248 err_code |= ERR_ALERT | ERR_FATAL;
5249 goto out;
5250 }
5251
5252 for (newul = userlist; newul; newul = newul->next)
5253 if (!strcmp(newul->name, args[1])) {
5254 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5255 file, linenum, args[1]);
5256 err_code |= ERR_WARN;
5257 goto out;
5258 }
5259
5260 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5261 if (!newul) {
5262 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5263 err_code |= ERR_ALERT | ERR_ABORT;
5264 goto out;
5265 }
5266
5267 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5268 newul->name = strdup(args[1]);
5269
5270 if (!newul->groupusers | !newul->name) {
5271 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5272 err_code |= ERR_ALERT | ERR_ABORT;
5273 goto out;
5274 }
5275
5276 newul->next = userlist;
5277 userlist = newul;
5278
5279 } else if (!strcmp(args[0], "group")) { /* new group */
5280 int cur_arg, i;
5281 const char *err;
5282
5283 if (!*args[1]) {
5284 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5285 file, linenum, args[0]);
5286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288 }
5289
5290 err = invalid_char(args[1]);
5291 if (err) {
5292 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5293 file, linenum, *err, args[0], args[1]);
5294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
5296 }
5297
5298 for(i = 0; i < userlist->grpcnt; i++)
5299 if (!strcmp(userlist->groups[i], args[1])) {
5300 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5301 file, linenum, args[1], userlist->name);
5302 err_code |= ERR_ALERT;
5303 goto out;
5304 }
5305
5306 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5307 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5308 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
5312
5313 cur_arg = 2;
5314
5315 while (*args[cur_arg]) {
5316 if (!strcmp(args[cur_arg], "users")) {
5317 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5318 cur_arg += 2;
5319 continue;
5320 } else {
5321 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5322 file, linenum, args[0]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326 }
5327
5328 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5329 } else if (!strcmp(args[0], "user")) { /* new user */
5330 struct auth_users *newuser;
5331 int cur_arg;
5332
5333 if (!*args[1]) {
5334 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5335 file, linenum, args[0]);
5336 err_code |= ERR_ALERT | ERR_FATAL;
5337 goto out;
5338 }
5339
5340 for (newuser = userlist->users; newuser; newuser = newuser->next)
5341 if (!strcmp(newuser->user, args[1])) {
5342 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5343 file, linenum, args[1], userlist->name);
5344 err_code |= ERR_ALERT;
5345 goto out;
5346 }
5347
5348 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5349 if (!newuser) {
5350 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5351 err_code |= ERR_ALERT | ERR_ABORT;
5352 goto out;
5353 }
5354
5355 newuser->user = strdup(args[1]);
5356
5357 newuser->next = userlist->users;
5358 userlist->users = newuser;
5359
5360 cur_arg = 2;
5361
5362 while (*args[cur_arg]) {
5363 if (!strcmp(args[cur_arg], "password")) {
5364#ifndef CONFIG_HAP_CRYPT
5365 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5366 file, linenum);
5367 err_code |= ERR_ALERT;
5368#endif
5369 newuser->pass = strdup(args[cur_arg + 1]);
5370 cur_arg += 2;
5371 continue;
5372 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5373 newuser->pass = strdup(args[cur_arg + 1]);
5374 newuser->flags |= AU_O_INSECURE;
5375 cur_arg += 2;
5376 continue;
5377 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005378 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005379 cur_arg += 2;
5380 continue;
5381 } else {
5382 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5383 file, linenum, args[0]);
5384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
5386 }
5387 }
5388 } else {
5389 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 }
5392
5393out:
5394 return err_code;
5395}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396
5397/*
5398 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005399 * Returns the error code, 0 if OK, or any combination of :
5400 * - ERR_ABORT: must abort ASAP
5401 * - ERR_FATAL: we can continue parsing but not start the service
5402 * - ERR_WARN: a warning has been emitted
5403 * - ERR_ALERT: an alert has been emitted
5404 * Only the two first ones can stop processing, the two others are just
5405 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005406 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005407int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005409 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 FILE *f;
5411 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005412 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005413 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005414
Willy Tarreaubaaee002006-06-26 02:48:02 +02005415 if ((f=fopen(file,"r")) == NULL)
5416 return -1;
5417
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005418 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005419 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005420 char *end;
5421 char *args[MAX_LINE_ARGS + 1];
5422 char *line = thisline;
5423
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 linenum++;
5425
5426 end = line + strlen(line);
5427
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005428 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5429 /* Check if we reached the limit and the last char is not \n.
5430 * Watch out for the last line without the terminating '\n'!
5431 */
5432 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005433 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005434 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005435 }
5436
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005438 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005439 line++;
5440
5441 arg = 0;
5442 args[arg] = line;
5443
5444 while (*line && arg < MAX_LINE_ARGS) {
5445 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5446 * C equivalent value. Other combinations left unchanged (eg: \1).
5447 */
5448 if (*line == '\\') {
5449 int skip = 0;
5450 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5451 *line = line[1];
5452 skip = 1;
5453 }
5454 else if (line[1] == 'r') {
5455 *line = '\r';
5456 skip = 1;
5457 }
5458 else if (line[1] == 'n') {
5459 *line = '\n';
5460 skip = 1;
5461 }
5462 else if (line[1] == 't') {
5463 *line = '\t';
5464 skip = 1;
5465 }
5466 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005467 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 unsigned char hex1, hex2;
5469 hex1 = toupper(line[2]) - '0';
5470 hex2 = toupper(line[3]) - '0';
5471 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5472 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5473 *line = (hex1<<4) + hex2;
5474 skip = 3;
5475 }
5476 else {
5477 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005478 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
5480 }
5481 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005482 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 end -= skip;
5484 }
5485 line++;
5486 }
5487 else if (*line == '#' || *line == '\n' || *line == '\r') {
5488 /* end of string, end of loop */
5489 *line = 0;
5490 break;
5491 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005492 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005494 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005495 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 line++;
5497 args[++arg] = line;
5498 }
5499 else {
5500 line++;
5501 }
5502 }
5503
5504 /* empty line */
5505 if (!**args)
5506 continue;
5507
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005508 if (*line) {
5509 /* we had to stop due to too many args.
5510 * Let's terminate the string, print the offending part then cut the
5511 * last arg.
5512 */
5513 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5514 line++;
5515 *line = '\0';
5516
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005517 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005518 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005519 err_code |= ERR_ALERT | ERR_FATAL;
5520 args[arg] = line;
5521 }
5522
Willy Tarreau540abe42007-05-02 20:50:16 +02005523 /* zero out remaining args and ensure that at least one entry
5524 * is zeroed out.
5525 */
5526 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527 args[arg] = line;
5528 }
5529
Willy Tarreau3842f002009-06-14 11:39:52 +02005530 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005531 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005532 char *tmp;
5533
Willy Tarreau3842f002009-06-14 11:39:52 +02005534 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005535 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005536 for (arg=0; *args[arg+1]; arg++)
5537 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005538 *tmp = '\0'; // fix the next arg to \0
5539 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005540 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005541 else if (!strcmp(args[0], "default")) {
5542 kwm = KWM_DEF;
5543 for (arg=0; *args[arg+1]; arg++)
5544 args[arg] = args[arg+1]; // shift args after inversion
5545 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005546
William Lallemand0f99e342011-10-12 17:50:54 +02005547 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5548 strcmp(args[0], "log") != 0) {
5549 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005551 }
5552
Willy Tarreau977b8e42006-12-29 14:19:17 +01005553 if (!strcmp(args[0], "listen") ||
5554 !strcmp(args[0], "frontend") ||
5555 !strcmp(args[0], "backend") ||
5556 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005557 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005559 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005560 cursection = strdup(args[0]);
5561 }
5562 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005564 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005565 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005566 }
5567 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005568 confsect = CFG_USERLIST;
5569 free(cursection);
5570 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005571 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005572 else if (!strcmp(args[0], "peers")) {
5573 confsect = CFG_PEERS;
5574 free(cursection);
5575 cursection = strdup(args[0]);
5576 }
5577
Willy Tarreaubaaee002006-06-26 02:48:02 +02005578 /* else it's a section keyword */
5579
5580 switch (confsect) {
5581 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 break;
5584 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005585 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005587 case CFG_USERLIST:
5588 err_code |= cfg_parse_users(file, linenum, args, kwm);
5589 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005590 case CFG_PEERS:
5591 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5592 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005594 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005595 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005596 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005597
5598 if (err_code & ERR_ABORT)
5599 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005601 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005602 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005603 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005604 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005605}
5606
Willy Tarreaubb925012009-07-23 13:36:36 +02005607/*
5608 * Returns the error code, 0 if OK, or any combination of :
5609 * - ERR_ABORT: must abort ASAP
5610 * - ERR_FATAL: we can continue parsing but not start the service
5611 * - ERR_WARN: a warning has been emitted
5612 * - ERR_ALERT: an alert has been emitted
5613 * Only the two first ones can stop processing, the two others are just
5614 * indicators.
5615 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005616int check_config_validity()
5617{
5618 int cfgerr = 0;
5619 struct proxy *curproxy = NULL;
5620 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005621 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005622 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005623 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624
5625 /*
5626 * Now, check for the integrity of all that we have collected.
5627 */
5628
5629 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005630 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005632 /* first, we will invert the proxy list order */
5633 curproxy = NULL;
5634 while (proxy) {
5635 struct proxy *next;
5636
5637 next = proxy->next;
5638 proxy->next = curproxy;
5639 curproxy = proxy;
5640 if (!next)
5641 break;
5642 proxy = next;
5643 }
5644
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005646 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005647 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005648 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005649 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005650 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005651 unsigned int next_id;
5652
5653 if (!curproxy->uuid) {
5654 /* proxy ID not set, use automatic numbering with first
5655 * spare entry starting with next_pxid.
5656 */
5657 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5658 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5659 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005660 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005661 next_pxid++;
5662
Willy Tarreau55ea7572007-06-17 19:56:27 +02005663
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005665 /* ensure we don't keep listeners uselessly bound */
5666 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005667 curproxy = curproxy->next;
5668 continue;
5669 }
5670
Willy Tarreauff01a212009-03-15 13:46:16 +01005671 switch (curproxy->mode) {
5672 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005673 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005674 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005675 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5676 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005677 cfgerr++;
5678 }
5679
5680 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005681 Warning("config : servers will be ignored for %s '%s'.\n",
5682 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005683 break;
5684
5685 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005686 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005687 break;
5688
5689 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005690 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005691 break;
5692 }
5693
5694 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005695 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5696 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 cfgerr++;
5698 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005699
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005700 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005701 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005702 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005703 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5704 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005705 cfgerr++;
5706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005707#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005708 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005709 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5710 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005711 cfgerr++;
5712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005714 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005715 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5716 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005717 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005718 }
5719 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005720 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005721 /* If no LB algo is set in a backend, and we're not in
5722 * transparent mode, dispatch mode nor proxy mode, we
5723 * want to use balance roundrobin by default.
5724 */
5725 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5726 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
5728 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005729
Willy Tarreau1620ec32011-08-06 17:05:02 +02005730 if (curproxy->options & PR_O_DISPATCH)
5731 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5732 else if (curproxy->options & PR_O_HTTP_PROXY)
5733 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5734 else if (curproxy->options & PR_O_TRANSP)
5735 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005736
Willy Tarreau1620ec32011-08-06 17:05:02 +02005737 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5738 if (curproxy->options & PR_O_DISABLE404) {
5739 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5740 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5741 err_code |= ERR_WARN;
5742 curproxy->options &= ~PR_O_DISABLE404;
5743 }
5744 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5745 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5746 "send-state", proxy_type_str(curproxy), curproxy->id);
5747 err_code |= ERR_WARN;
5748 curproxy->options &= ~PR_O2_CHK_SNDST;
5749 }
Willy Tarreauef781042010-01-27 11:53:01 +01005750 }
5751
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005752 /* if a default backend was specified, let's find it */
5753 if (curproxy->defbe.name) {
5754 struct proxy *target;
5755
Alex Williams96532db2009-11-01 21:27:13 -05005756 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005757 if (!target) {
5758 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5759 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005760 cfgerr++;
5761 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005762 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5763 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005764 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005765 } else {
5766 free(curproxy->defbe.name);
5767 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005768 /* we force the backend to be present on at least all of
5769 * the frontend's processes.
5770 */
5771 target->bind_proc = curproxy->bind_proc ?
5772 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005773
5774 /* Emit a warning if this proxy also has some servers */
5775 if (curproxy->srv) {
5776 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5777 curproxy->id);
5778 err_code |= ERR_WARN;
5779 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780 }
5781 }
5782
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005783 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005784 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5785 /* map jump target for ACT_SETBE in req_rep chain */
5786 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005787 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005788 struct proxy *target;
5789
Willy Tarreaua496b602006-12-17 23:15:24 +01005790 if (exp->action != ACT_SETBE)
5791 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005792
Alex Williams96532db2009-11-01 21:27:13 -05005793 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005794 if (!target) {
5795 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5796 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005797 cfgerr++;
5798 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005799 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5800 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005801 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005802 } else {
5803 free((void *)exp->replace);
5804 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005805 /* we force the backend to be present on at least all of
5806 * the frontend's processes.
5807 */
5808 target->bind_proc = curproxy->bind_proc ?
5809 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005810 }
5811 }
5812 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005813
5814 /* find the target proxy for 'use_backend' rules */
5815 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005816 struct proxy *target;
5817
Alex Williams96532db2009-11-01 21:27:13 -05005818 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005819
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005820 if (!target) {
5821 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5822 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005823 cfgerr++;
5824 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005825 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5826 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005827 cfgerr++;
5828 } else {
5829 free((void *)rule->be.name);
5830 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005831 /* we force the backend to be present on at least all of
5832 * the frontend's processes.
5833 */
5834 target->bind_proc = curproxy->bind_proc ?
5835 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005836 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005837 }
5838
5839 /* find the target proxy for 'use_backend' rules */
5840 list_for_each_entry(srule, &curproxy->server_rules, list) {
5841 struct server *target = findserver(curproxy, srule->srv.name);
5842
5843 if (!target) {
5844 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5845 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5846 cfgerr++;
5847 continue;
5848 }
5849 free((void *)srule->srv.name);
5850 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005851 }
5852
Emeric Brunb982a3d2010-01-04 15:45:53 +01005853 /* find the target table for 'stick' rules */
5854 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5855 struct proxy *target;
5856
Emeric Brun1d33b292010-01-04 15:47:17 +01005857 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5858 if (mrule->flags & STK_IS_STORE)
5859 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5860
Emeric Brunb982a3d2010-01-04 15:45:53 +01005861 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005862 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005863 else
5864 target = curproxy;
5865
5866 if (!target) {
5867 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5868 curproxy->id, mrule->table.name);
5869 cfgerr++;
5870 }
5871 else if (target->table.size == 0) {
5872 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5873 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5874 cfgerr++;
5875 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005876 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005877 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5878 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5879 cfgerr++;
5880 }
5881 else {
5882 free((void *)mrule->table.name);
5883 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005884 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005885 }
5886 }
5887
5888 /* find the target table for 'store response' rules */
5889 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5890 struct proxy *target;
5891
Emeric Brun1d33b292010-01-04 15:47:17 +01005892 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5893
Emeric Brunb982a3d2010-01-04 15:45:53 +01005894 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005895 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005896 else
5897 target = curproxy;
5898
5899 if (!target) {
5900 Alert("Proxy '%s': unable to find store table '%s'.\n",
5901 curproxy->id, mrule->table.name);
5902 cfgerr++;
5903 }
5904 else if (target->table.size == 0) {
5905 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5906 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5907 cfgerr++;
5908 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005909 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005910 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5911 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5912 cfgerr++;
5913 }
5914 else {
5915 free((void *)mrule->table.name);
5916 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005917 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005918 }
5919 }
5920
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005921 /* find the target table for 'tcp-request' layer 4 rules */
5922 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5923 struct proxy *target;
5924
Willy Tarreau56123282010-08-06 19:06:56 +02005925 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005926 continue;
5927
5928 if (trule->act_prm.trk_ctr.table.n)
5929 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5930 else
5931 target = curproxy;
5932
5933 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005934 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5935 curproxy->id, trule->act_prm.trk_ctr.table.n,
5936 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005937 cfgerr++;
5938 }
5939 else if (target->table.size == 0) {
5940 Alert("Proxy '%s': table '%s' used but not configured.\n",
5941 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5942 cfgerr++;
5943 }
5944 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005945 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 +02005946 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5947 cfgerr++;
5948 }
5949 else {
5950 free(trule->act_prm.trk_ctr.table.n);
5951 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005952 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005953 * to pass a list of counters to track and allocate them right here using
5954 * stktable_alloc_data_type().
5955 */
5956 }
5957 }
5958
Willy Tarreaud1f96522010-08-03 19:34:32 +02005959 /* find the target table for 'tcp-request' layer 6 rules */
5960 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5961 struct proxy *target;
5962
Willy Tarreau56123282010-08-06 19:06:56 +02005963 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005964 continue;
5965
5966 if (trule->act_prm.trk_ctr.table.n)
5967 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5968 else
5969 target = curproxy;
5970
5971 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005972 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5973 curproxy->id, trule->act_prm.trk_ctr.table.n,
5974 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02005975 cfgerr++;
5976 }
5977 else if (target->table.size == 0) {
5978 Alert("Proxy '%s': table '%s' used but not configured.\n",
5979 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5980 cfgerr++;
5981 }
5982 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005983 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 +02005984 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5985 cfgerr++;
5986 }
5987 else {
5988 free(trule->act_prm.trk_ctr.table.n);
5989 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005990 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02005991 * to pass a list of counters to track and allocate them right here using
5992 * stktable_alloc_data_type().
5993 */
5994 }
5995 }
5996
Emeric Brun32da3c42010-09-23 18:39:19 +02005997 if (curproxy->table.peers.name) {
5998 struct peers *curpeers = peers;
5999
6000 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6001 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6002 free((void *)curproxy->table.peers.name);
6003 curproxy->table.peers.p = peers;
6004 break;
6005 }
6006 }
6007
6008 if (!curpeers) {
6009 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6010 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006011 free((void *)curproxy->table.peers.name);
6012 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006013 cfgerr++;
6014 }
6015 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006016 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6017 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006018 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006019 cfgerr++;
6020 }
6021 }
6022
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006023 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006024 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006025 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6026 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6027 "proxy", curproxy->id);
6028 cfgerr++;
6029 goto out_uri_auth_compat;
6030 }
6031
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006032 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006033 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006034 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006035 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006036
Willy Tarreau95fa4692010-02-01 13:05:50 +01006037 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6038 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006039
6040 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006041 uri_auth_compat_req[i++] = "realm";
6042 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6043 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006044
Willy Tarreau95fa4692010-02-01 13:05:50 +01006045 uri_auth_compat_req[i++] = "unless";
6046 uri_auth_compat_req[i++] = "{";
6047 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6048 uri_auth_compat_req[i++] = "}";
6049 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006050
Willy Tarreauff011f22011-01-06 17:51:27 +01006051 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6052 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006053 cfgerr++;
6054 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006055 }
6056
Willy Tarreauff011f22011-01-06 17:51:27 +01006057 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006058
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006059 if (curproxy->uri_auth->auth_realm) {
6060 free(curproxy->uri_auth->auth_realm);
6061 curproxy->uri_auth->auth_realm = NULL;
6062 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006063
6064 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006065 }
6066out_uri_auth_compat:
6067
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006068 cfgerr += acl_find_targets(curproxy);
6069
Willy Tarreau2738a142006-07-08 17:28:09 +02006070 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006071 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006072 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006073 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006074 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006075 " | While not properly invalid, you will certainly encounter various problems\n"
6076 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006077 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006078 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006079 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006080 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006081
Willy Tarreau1fa31262007-12-03 00:36:16 +01006082 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6083 * We must still support older configurations, so let's find out whether those
6084 * parameters have been set or must be copied from contimeouts.
6085 */
6086 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006087 if (!curproxy->timeout.tarpit ||
6088 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006089 /* tarpit timeout not set. We search in the following order:
6090 * default.tarpit, curr.connect, default.connect.
6091 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006092 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006093 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006094 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006095 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006096 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006097 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006098 }
6099 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006100 (!curproxy->timeout.queue ||
6101 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006102 /* queue timeout not set. We search in the following order:
6103 * default.queue, curr.connect, default.connect.
6104 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006105 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006106 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006107 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006108 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006109 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006110 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006111 }
6112 }
6113
Willy Tarreau1620ec32011-08-06 17:05:02 +02006114 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006115 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6116 curproxy->check_req = (char *)malloc(curproxy->check_len);
6117 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006118 }
6119
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006120 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006121 if (curproxy->nb_req_cap) {
6122 if (curproxy->mode == PR_MODE_HTTP) {
6123 curproxy->req_cap_pool = create_pool("ptrcap",
6124 curproxy->nb_req_cap * sizeof(char *),
6125 MEM_F_SHARED);
6126 } else {
6127 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6128 proxy_type_str(curproxy), curproxy->id);
6129 err_code |= ERR_WARN;
6130 curproxy->to_log &= ~LW_REQHDR;
6131 curproxy->nb_req_cap = 0;
6132 }
6133 }
6134
6135 if (curproxy->nb_rsp_cap) {
6136 if (curproxy->mode == PR_MODE_HTTP) {
6137 curproxy->rsp_cap_pool = create_pool("ptrcap",
6138 curproxy->nb_rsp_cap * sizeof(char *),
6139 MEM_F_SHARED);
6140 } else {
6141 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6142 proxy_type_str(curproxy), curproxy->id);
6143 err_code |= ERR_WARN;
6144 curproxy->to_log &= ~LW_REQHDR;
6145 curproxy->nb_rsp_cap = 0;
6146 }
6147 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006148
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 /* first, we will invert the servers list order */
6150 newsrv = NULL;
6151 while (curproxy->srv) {
6152 struct server *next;
6153
6154 next = curproxy->srv->next;
6155 curproxy->srv->next = newsrv;
6156 newsrv = curproxy->srv;
6157 if (!next)
6158 break;
6159 curproxy->srv = next;
6160 }
6161
Willy Tarreaudd701652010-05-25 23:03:02 +02006162 /* assign automatic UIDs to servers which don't have one yet */
6163 next_id = 1;
6164 newsrv = curproxy->srv;
6165 while (newsrv != NULL) {
6166 if (!newsrv->puid) {
6167 /* server ID not set, use automatic numbering with first
6168 * spare entry starting with next_svid.
6169 */
6170 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6171 newsrv->conf.id.key = newsrv->puid = next_id;
6172 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6173 }
6174 next_id++;
6175 newsrv = newsrv->next;
6176 }
6177
Willy Tarreau20697042007-11-15 23:26:18 +01006178 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006179 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006180
Willy Tarreau62c3be22012-01-20 13:12:32 +01006181 /*
6182 * If this server supports a maxconn parameter, it needs a dedicated
6183 * tasks to fill the emptied slots when a connection leaves.
6184 * Also, resolve deferred tracking dependency if needed.
6185 */
6186 newsrv = curproxy->srv;
6187 while (newsrv != NULL) {
6188 if (newsrv->minconn > newsrv->maxconn) {
6189 /* Only 'minconn' was specified, or it was higher than or equal
6190 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6191 * this will avoid further useless expensive computations.
6192 */
6193 newsrv->maxconn = newsrv->minconn;
6194 } else if (newsrv->maxconn && !newsrv->minconn) {
6195 /* minconn was not specified, so we set it to maxconn */
6196 newsrv->minconn = newsrv->maxconn;
6197 }
6198
6199 if (newsrv->trackit) {
6200 struct proxy *px;
6201 struct server *srv;
6202 char *pname, *sname;
6203
6204 pname = newsrv->trackit;
6205 sname = strrchr(pname, '/');
6206
6207 if (sname)
6208 *sname++ = '\0';
6209 else {
6210 sname = pname;
6211 pname = NULL;
6212 }
6213
6214 if (pname) {
6215 px = findproxy(pname, PR_CAP_BE);
6216 if (!px) {
6217 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6218 proxy_type_str(curproxy), curproxy->id,
6219 newsrv->id, pname);
6220 cfgerr++;
6221 goto next_srv;
6222 }
6223 } else
6224 px = curproxy;
6225
6226 srv = findserver(px, sname);
6227 if (!srv) {
6228 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6229 proxy_type_str(curproxy), curproxy->id,
6230 newsrv->id, sname);
6231 cfgerr++;
6232 goto next_srv;
6233 }
6234
6235 if (!(srv->state & SRV_CHECKED)) {
6236 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6237 "tracking as it does not have checks enabled.\n",
6238 proxy_type_str(curproxy), curproxy->id,
6239 newsrv->id, px->id, srv->id);
6240 cfgerr++;
6241 goto next_srv;
6242 }
6243
6244 if (curproxy != px &&
6245 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6246 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6247 "tracking: disable-on-404 option inconsistency.\n",
6248 proxy_type_str(curproxy), curproxy->id,
6249 newsrv->id, px->id, srv->id);
6250 cfgerr++;
6251 goto next_srv;
6252 }
6253
6254 /* if the other server is forced disabled, we have to do the same here */
6255 if (srv->state & SRV_MAINTAIN) {
6256 newsrv->state |= SRV_MAINTAIN;
6257 newsrv->state &= ~SRV_RUNNING;
6258 newsrv->health = 0;
6259 }
6260
6261 newsrv->track = srv;
6262 newsrv->tracknext = srv->tracknext;
6263 srv->tracknext = newsrv;
6264
6265 free(newsrv->trackit);
6266 newsrv->trackit = NULL;
6267 }
6268 next_srv:
6269 newsrv = newsrv->next;
6270 }
6271
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006272 /* We have to initialize the server lookup mechanism depending
6273 * on what LB algorithm was choosen.
6274 */
6275
6276 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6277 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6278 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006279 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6280 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6281 init_server_map(curproxy);
6282 } else {
6283 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6284 fwrr_init_server_groups(curproxy);
6285 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006286 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006287
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006288 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006289 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6290 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6291 fwlc_init_server_tree(curproxy);
6292 } else {
6293 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6294 fas_init_server_tree(curproxy);
6295 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006296 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006297
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006298 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006299 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6300 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6301 chash_init_server_tree(curproxy);
6302 } else {
6303 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6304 init_server_map(curproxy);
6305 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006306 break;
6307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308
6309 if (curproxy->options & PR_O_LOGASAP)
6310 curproxy->to_log &= ~LW_BYTES;
6311
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006312 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006313 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006314 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6315 proxy_type_str(curproxy), curproxy->id);
6316 err_code |= ERR_WARN;
6317 }
6318
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006319 if (curproxy->mode != PR_MODE_HTTP) {
6320 int optnum;
6321
6322 if (curproxy->options & PR_O_COOK_ANY) {
6323 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6324 proxy_type_str(curproxy), curproxy->id);
6325 err_code |= ERR_WARN;
6326 }
6327
6328 if (curproxy->uri_auth) {
6329 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6330 proxy_type_str(curproxy), curproxy->id);
6331 err_code |= ERR_WARN;
6332 curproxy->uri_auth = NULL;
6333 }
6334
Willy Tarreau87cf5142011-08-19 22:57:24 +02006335 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006336 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6337 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6338 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006339 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006340 }
6341
6342 if (curproxy->options & PR_O_ORGTO) {
6343 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6344 "originalto", proxy_type_str(curproxy), curproxy->id);
6345 err_code |= ERR_WARN;
6346 curproxy->options &= ~PR_O_ORGTO;
6347 }
6348
6349 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6350 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6351 (curproxy->cap & cfg_opts[optnum].cap) &&
6352 (curproxy->options & cfg_opts[optnum].val)) {
6353 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6354 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6355 err_code |= ERR_WARN;
6356 curproxy->options &= ~cfg_opts[optnum].val;
6357 }
6358 }
6359
6360 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6361 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6362 (curproxy->cap & cfg_opts2[optnum].cap) &&
6363 (curproxy->options2 & cfg_opts2[optnum].val)) {
6364 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6365 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6366 err_code |= ERR_WARN;
6367 curproxy->options2 &= ~cfg_opts2[optnum].val;
6368 }
6369 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006370
Willy Tarreauefa5f512010-03-30 20:13:29 +02006371#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006372 if (curproxy->bind_hdr_occ) {
6373 curproxy->bind_hdr_occ = 0;
6374 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6375 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6376 err_code |= ERR_WARN;
6377 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006378#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006379 }
6380
Willy Tarreaubaaee002006-06-26 02:48:02 +02006381 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006382 * ensure that we're not cross-dressing a TCP server into HTTP.
6383 */
6384 newsrv = curproxy->srv;
6385 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006386 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006387 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6388 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006389 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006390 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006391
Willy Tarreau0cec3312011-10-31 13:49:26 +01006392 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6393 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6394 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6395 err_code |= ERR_WARN;
6396 }
6397
Willy Tarreauefa5f512010-03-30 20:13:29 +02006398#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006399 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6400 newsrv->bind_hdr_occ = 0;
6401 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6402 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6403 err_code |= ERR_WARN;
6404 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006405#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006406 newsrv = newsrv->next;
6407 }
6408
Willy Tarreauc1a21672009-08-16 22:37:44 +02006409 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006410 curproxy->accept = frontend_accept;
6411
Willy Tarreauc1a21672009-08-16 22:37:44 +02006412 if (curproxy->tcp_req.inspect_delay ||
6413 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006414 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006415
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006416 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006417 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006418 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006419 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006420
6421 /* both TCP and HTTP must check switching rules */
6422 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6423 }
6424
6425 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006426 if (curproxy->tcp_req.inspect_delay ||
6427 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6428 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6429
Emeric Brun97679e72010-09-23 17:56:44 +02006430 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6431 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6432
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006433 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006434 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006435 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006436 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006437
6438 /* If the backend does requires RDP cookie persistence, we have to
6439 * enable the corresponding analyser.
6440 */
6441 if (curproxy->options2 & PR_O2_RDPC_PRST)
6442 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6443 }
6444
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006445 listener = NULL;
6446 while (curproxy->listen) {
6447 struct listener *next;
6448
6449 next = curproxy->listen->next;
6450 curproxy->listen->next = listener;
6451 listener = curproxy->listen;
6452
6453 if (!next)
6454 break;
6455
6456 curproxy->listen = next;
6457 }
6458
Willy Tarreaue6b98942007-10-29 01:09:36 +01006459 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006460 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006461 listener = curproxy->listen;
6462 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006463 if (!listener->luid) {
6464 /* listener ID not set, use automatic numbering with first
6465 * spare entry starting with next_luid.
6466 */
6467 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6468 listener->conf.id.key = listener->luid = next_id;
6469 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006470 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006471 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006472
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006473 /* enable separate counters */
6474 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6475 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6476 if (!listener->name) {
6477 sprintf(trash, "sock-%d", listener->luid);
6478 listener->name = strdup(trash);
6479 }
6480 }
6481
Willy Tarreaue6b98942007-10-29 01:09:36 +01006482 if (curproxy->options & PR_O_TCP_NOLING)
6483 listener->options |= LI_O_NOLINGER;
6484 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006485 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006486 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006487 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006488 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006489 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006490 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006491
Willy Tarreau8a956912010-10-15 14:27:08 +02006492 if (listener->options & LI_O_ACC_PROXY)
6493 listener->analysers |= AN_REQ_DECODE_PROXY;
6494
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006495 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6496 listener->options |= LI_O_TCP_RULES;
6497
Willy Tarreaude3041d2010-05-31 10:56:17 +02006498 if (curproxy->mon_mask.s_addr)
6499 listener->options |= LI_O_CHK_MONNET;
6500
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006501 /* smart accept mode is automatic in HTTP mode */
6502 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6503 (curproxy->mode == PR_MODE_HTTP &&
6504 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6505 listener->options |= LI_O_NOQUICKACK;
6506
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006507 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006508 listener = listener->next;
6509 }
6510
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006511 /* Check multi-process mode compatibility for the current proxy */
6512 if (global.nbproc > 1) {
6513 int nbproc = 0;
6514 if (curproxy->bind_proc) {
6515 int proc;
6516 for (proc = 0; proc < global.nbproc; proc++) {
6517 if (curproxy->bind_proc & (1 << proc)) {
6518 nbproc++;
6519 }
6520 }
6521 } else {
6522 nbproc = global.nbproc;
6523 }
6524 if (curproxy->table.peers.name) {
6525 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6526 curproxy->id);
6527 cfgerr++;
6528 }
6529 if (nbproc > 1) {
6530 if (curproxy->uri_auth) {
6531 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6532 curproxy->id);
6533 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6534 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6535 curproxy->id);
6536 }
6537 }
6538 if (curproxy->appsession_name) {
6539 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6540 curproxy->id);
6541 }
6542 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6543 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6544 curproxy->id);
6545 }
6546 }
6547 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006548
6549 /* create the task associated with the proxy */
6550 curproxy->task = task_new();
6551 if (curproxy->task) {
6552 curproxy->task->context = curproxy;
6553 curproxy->task->process = manage_proxy;
6554 /* no need to queue, it will be done automatically if some
6555 * listener gets limited.
6556 */
6557 curproxy->task->expire = TICK_ETERNITY;
6558 } else {
6559 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6560 curproxy->id);
6561 cfgerr++;
6562 }
6563
Willy Tarreaubaaee002006-06-26 02:48:02 +02006564 curproxy = curproxy->next;
6565 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006566
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006567 /* Check multi-process mode compatibility */
6568 if (global.nbproc > 1) {
6569 if (global.stats_fe) {
6570 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6571 }
6572 }
6573
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006574 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6575 struct auth_users *curuser;
6576 int g;
6577
6578 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6579 unsigned int group_mask = 0;
6580 char *group = NULL;
6581
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006582 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006583 continue;
6584
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006585 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006586
6587 for (g = 0; g < curuserlist->grpcnt; g++)
6588 if (!strcmp(curuserlist->groups[g], group))
6589 break;
6590
6591 if (g == curuserlist->grpcnt) {
6592 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6593 curuserlist->name, group, curuser->user);
6594 err_code |= ERR_ALERT | ERR_FATAL;
6595 goto out;
6596 }
6597
6598 group_mask |= (1 << g);
6599 }
6600
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006601 free(curuser->u.groups);
6602 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006603 }
6604
6605 for (g = 0; g < curuserlist->grpcnt; g++) {
6606 char *user = NULL;
6607
6608 if (!curuserlist->groupusers[g])
6609 continue;
6610
6611 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6612 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6613 if (!strcmp(curuser->user, user))
6614 break;
6615
6616 if (!curuser) {
6617 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6618 curuserlist->name, user, curuserlist->groups[g]);
6619 err_code |= ERR_ALERT | ERR_FATAL;
6620 goto out;
6621 }
6622
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006623 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006624 }
6625
6626 free(curuserlist->groupusers[g]);
6627 }
6628
6629 free(curuserlist->groupusers);
6630
6631#ifdef DEBUG_AUTH
6632 for (g = 0; g < curuserlist->grpcnt; g++) {
6633 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6634
6635 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6636 if (curuser->group_mask & (1 << g))
6637 fprintf(stderr, " %s", curuser->user);
6638 }
6639
6640 fprintf(stderr, "\n");
6641 }
6642#endif
6643
Willy Tarreaufbb78422011-06-05 15:38:35 +02006644 }
6645
6646 /* automatically compute fullconn if not set. We must not do it in the
6647 * loop above because cross-references are not yet fully resolved.
6648 */
6649 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6650 /* If <fullconn> is not set, let's set it to 10% of the sum of
6651 * the possible incoming frontend's maxconns.
6652 */
6653 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6654 struct proxy *fe;
6655 int total = 0;
6656
6657 /* sum up the number of maxconns of frontends which
6658 * reference this backend at least once or which are
6659 * the same one ('listen').
6660 */
6661 for (fe = proxy; fe; fe = fe->next) {
6662 struct switching_rule *rule;
6663 struct hdr_exp *exp;
6664 int found = 0;
6665
6666 if (!(fe->cap & PR_CAP_FE))
6667 continue;
6668
6669 if (fe == curproxy) /* we're on a "listen" instance */
6670 found = 1;
6671
6672 if (fe->defbe.be == curproxy) /* "default_backend" */
6673 found = 1;
6674
6675 /* check if a "use_backend" rule matches */
6676 if (!found) {
6677 list_for_each_entry(rule, &fe->switching_rules, list) {
6678 if (rule->be.backend == curproxy) {
6679 found = 1;
6680 break;
6681 }
6682 }
6683 }
6684
6685 /* check if a "reqsetbe" rule matches */
6686 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6687 if (exp->action == ACT_SETBE &&
6688 (struct proxy *)exp->replace == curproxy) {
6689 found = 1;
6690 break;
6691 }
6692 }
6693
6694 /* now we've checked all possible ways to reference a backend
6695 * from a frontend.
6696 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006697 if (!found)
6698 continue;
6699 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006700 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006701 /* we have the sum of the maxconns in <total>. We only
6702 * keep 10% of that sum to set the default fullconn, with
6703 * a hard minimum of 1 (to avoid a divide by zero).
6704 */
6705 curproxy->fullconn = (total + 9) / 10;
6706 if (!curproxy->fullconn)
6707 curproxy->fullconn = 1;
6708 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006709 }
6710
Willy Tarreau056f5682010-06-06 15:51:11 +02006711 /* initialize stick-tables on backend capable proxies. This must not
6712 * be done earlier because the data size may be discovered while parsing
6713 * other proxies.
6714 */
6715 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006716 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006717
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006718 /*
6719 * Recount currently required checks.
6720 */
6721
6722 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6723 int optnum;
6724
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006725 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6726 if (curproxy->options & cfg_opts[optnum].val)
6727 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006728
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006729 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6730 if (curproxy->options2 & cfg_opts2[optnum].val)
6731 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006732 }
6733
Willy Tarreau122541c2011-09-07 21:24:49 +02006734 if (peers) {
6735 struct peers *curpeers = peers, **last;
6736 struct peer *p, *pb;
6737
6738 /* Remove all peers sections which don't have a valid listener.
6739 * This can happen when a peers section is never referenced and
6740 * does not contain a local peer.
6741 */
6742 last = &peers;
6743 while (*last) {
6744 curpeers = *last;
6745 if (curpeers->peers_fe) {
6746 last = &curpeers->next;
6747 continue;
6748 }
6749
6750 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6751 curpeers->id, localpeer);
6752
6753 p = curpeers->remote;
6754 while (p) {
6755 pb = p->next;
6756 free(p->id);
6757 free(p);
6758 p = pb;
6759 }
6760
6761 /* Destroy and unlink this curpeers section.
6762 * Note: curpeers is backed up into *last.
6763 */
6764 free(curpeers->id);
6765 curpeers = curpeers->next;
6766 free(*last);
6767 *last = curpeers;
6768 }
6769 }
6770
Willy Tarreauac1932d2011-10-24 19:14:41 +02006771 if (!global.tune.max_http_hdr)
6772 global.tune.max_http_hdr = MAX_HTTP_HDR;
6773
Willy Tarreau34eb6712011-10-24 18:15:04 +02006774 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006775 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006776 MEM_F_SHARED);
6777
Willy Tarreaubb925012009-07-23 13:36:36 +02006778 if (cfgerr > 0)
6779 err_code |= ERR_ALERT | ERR_FATAL;
6780 out:
6781 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006782}
6783
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006784/*
6785 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6786 * parsing sessions.
6787 */
6788void cfg_register_keywords(struct cfg_kw_list *kwl)
6789{
6790 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6791}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006792
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006793/*
6794 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6795 */
6796void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6797{
6798 LIST_DEL(&kwl->list);
6799 LIST_INIT(&kwl->list);
6800}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006801
6802/*
6803 * Local variables:
6804 * c-indent-level: 8
6805 * c-basic-offset: 8
6806 * End:
6807 */