blob: c623927b336bf9bff0d11860b597d6d4e89ac545 [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>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020054#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010055#include <proto/protocols.h>
56#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020057#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010058#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010059#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020060#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020061#include <proto/sample.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 Tarreaud02394b2012-05-11 18:32:18 +020064#include <proto/sock_raw.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010066#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
68
Willy Tarreauf3c69202006-07-09 16:42:34 +020069/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
70 * ssl-hello-chk option to ensure that the remote server speaks SSL.
71 *
72 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
73 */
74const char sslv3_client_hello_pkt[] = {
75 "\x16" /* ContentType : 0x16 = Hanshake */
76 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
77 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
78 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
79 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
80 "\x03\x00" /* Hello Version : 0x0300 = v3 */
81 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
82 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
83 "\x00" /* Session ID length : empty (no session ID) */
84 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
85 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
86 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
87 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
88 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
89 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
90 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
91 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
92 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
93 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
94 "\x00\x38" "\x00\x39" "\x00\x3A"
95 "\x01" /* Compression Length : 0x01 = 1 byte for types */
96 "\x00" /* Compression Type : 0x00 = NULL compression */
97};
98
Willy Tarreau3842f002009-06-14 11:39:52 +020099/* various keyword modifiers */
100enum kw_mod {
101 KWM_STD = 0, /* normal */
102 KWM_NO, /* "no" prefixed before the keyword */
103 KWM_DEF, /* "default" prefixed before the keyword */
104};
105
Willy Tarreau13943ab2006-12-31 00:24:10 +0100106/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100107struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100108 const char *name;
109 unsigned int val;
110 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100111 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100112 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100113};
114
115/* proxy->options */
116static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100117{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100118 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
119 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
120 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
121 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
122 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
123 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
124 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
128 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
130 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
131 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
132 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
133 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100134#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100135 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100136#else
137 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100138#endif
139
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141};
142
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143/* proxy->options2 */
144static const struct cfg_opt cfg_opts2[] =
145{
146#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
148 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
149 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100150#else
151 { "splice-request", 0, 0, 0, 0 },
152 { "splice-response", 0, 0, 0, 0 },
153 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100154#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
156 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
157 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
158 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
159 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
160 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
161 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
162 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
163 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400164 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200166 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200167 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100168 { NULL, 0, 0, 0 }
169};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170
Willy Tarreau6daf3432008-01-22 16:44:08 +0100171static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
173int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100174int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200176/* List head of all known configuration keywords */
177static struct cfg_kw_list cfg_keywords = {
178 .list = LIST_HEAD_INIT(cfg_keywords.list)
179};
180
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181/*
182 * converts <str> to a list of listeners which are dynamically allocated.
183 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
184 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
185 * - <port> is a numerical port from 1 to 65535 ;
186 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
187 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200188 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100190static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191{
192 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100193 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194 int port, end;
195
196 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200197
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198 while (next && *next) {
199 struct sockaddr_storage ss;
200
201 str = next;
202 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100203 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 *next++ = 0;
205 }
206
Emeric Bruned760922010-10-22 17:59:25 +0200207 if (*str == '/') {
208 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
209 /* so compute max path */
210 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
211 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 +0200212
Emeric Bruned760922010-10-22 17:59:25 +0200213 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100214 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
215 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200216 goto fail;
217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200220 ss.ss_family = AF_UNIX;
221 if (global.unix_bind.prefix) {
222 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
223 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 }
Emeric Bruned760922010-10-22 17:59:25 +0200225 else {
226 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
227 }
228 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 }
230 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100231 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100233 ss2 = str2sa_range(str, &port, &end);
234 if (!ss2) {
235 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
236 file, line, str);
237 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 if (!port) {
241 Alert("parsing [%s:%d] : missing port number: '%s'\n",
242 file, line, str);
243 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 /* OK the address looks correct */
247 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Emeric Bruned760922010-10-22 17:59:25 +0200249 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
251 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200252 goto fail;
253 }
254
255 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100256 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
257 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200260 }
261
262 for (; port <= end; port++) {
263 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200264 l->next = curproxy->listen;
265 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266
267 l->fd = -1;
268 l->addr = ss;
Emeric Brund88fd822012-05-18 18:30:29 +0200269 l->sock = &sock_raw;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100270 l->state = LI_INIT;
271
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100272 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 tcpv4_add_listener(l);
275 }
Emeric Bruned760922010-10-22 17:59:25 +0200276 else if (ss.ss_family == AF_INET6) {
277 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
278 tcpv6_add_listener(l);
279 }
280 else {
281 l->perm.ux.gid = l->perm.ux.uid = -1;
282 l->perm.ux.mode = 0;
283 uxst_add_listener(l);
284 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200285
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200286 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100287 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 } /* end for(port) */
289 } /* end while(next) */
290 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 fail:
293 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200294 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295}
296
Willy Tarreau977b8e42006-12-29 14:19:17 +0100297/*
298 * Sends a warning if proxy <proxy> does not have at least one of the
299 * capabilities in <cap>. An optionnal <hint> may be added at the end
300 * of the warning to help the user. Returns 1 if a warning was emitted
301 * or 0 if the condition is valid.
302 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100303int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100304{
305 char *msg;
306
307 switch (cap) {
308 case PR_CAP_BE: msg = "no backend"; break;
309 case PR_CAP_FE: msg = "no frontend"; break;
310 case PR_CAP_RS: msg = "no ruleset"; break;
311 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
312 default: msg = "not enough"; break;
313 }
314
315 if (!(proxy->cap & cap)) {
316 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100317 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100318 return 1;
319 }
320 return 0;
321}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322
Willy Tarreau61d18892009-03-31 10:49:21 +0200323/* Report a warning if a rule is placed after a 'block' rule.
324 * Return 1 if the warning has been emitted, otherwise 0.
325 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100326int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200327{
328 if (!LIST_ISEMPTY(&proxy->block_cond)) {
329 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
330 file, line, arg);
331 return 1;
332 }
333 return 0;
334}
335
336/* Report a warning if a rule is placed after a reqrewrite rule.
337 * Return 1 if the warning has been emitted, otherwise 0.
338 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100339int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200340{
341 if (proxy->req_exp) {
342 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
343 file, line, arg);
344 return 1;
345 }
346 return 0;
347}
348
349/* Report a warning if a rule is placed after a reqadd rule.
350 * Return 1 if the warning has been emitted, otherwise 0.
351 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100352int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200353{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100354 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200355 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
356 file, line, arg);
357 return 1;
358 }
359 return 0;
360}
361
362/* Report a warning if a rule is placed after a redirect rule.
363 * Return 1 if the warning has been emitted, otherwise 0.
364 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100365int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200366{
367 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
368 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
369 file, line, arg);
370 return 1;
371 }
372 return 0;
373}
374
375/* Report a warning if a rule is placed after a 'use_backend' rule.
376 * Return 1 if the warning has been emitted, otherwise 0.
377 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100378int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200379{
380 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
381 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
382 file, line, arg);
383 return 1;
384 }
385 return 0;
386}
387
388/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
392 warnif_rule_after_reqadd(proxy, file, line, arg) ||
393 warnif_rule_after_redirect(proxy, file, line, arg) ||
394 warnif_rule_after_use_backend(proxy, file, line, arg);
395}
396
397/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100398int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200399{
400 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
401 warnif_rule_after_redirect(proxy, file, line, arg) ||
402 warnif_rule_after_use_backend(proxy, file, line, arg);
403}
404
405/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100406int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200407{
408 return warnif_rule_after_redirect(proxy, file, line, arg) ||
409 warnif_rule_after_use_backend(proxy, file, line, arg);
410}
411
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100412/* Report it if a request ACL condition uses some response-only parameters. It
413 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
414 * Note that <cond> may be NULL and then will be ignored.
415 */
416static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
417{
418 struct acl *acl;
419
420 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
421 return 0;
422
423 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
424 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
425 file, line, acl ? acl->name : "(unknown)");
426 return ERR_WARN;
427}
428
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100429/* Report it if a request ACL condition uses some request-only volatile parameters.
430 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
431 * Note that <cond> may be NULL and then will be ignored.
432 */
433static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
434{
435 struct acl *acl;
436
437 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
438 return 0;
439
440 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
441 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
442 file, line, acl ? acl->name : "(unknown)");
443 return ERR_WARN;
444}
445
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100446
Willy Tarreaubaaee002006-06-26 02:48:02 +0200447/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200448 * parse a line in a <global> section. Returns the error code, 0 if OK, or
449 * any combination of :
450 * - ERR_ABORT: must abort ASAP
451 * - ERR_FATAL: we can continue parsing but not start the service
452 * - ERR_WARN: a warning has been emitted
453 * - ERR_ALERT: an alert has been emitted
454 * Only the two first ones can stop processing, the two others are just
455 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200456 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200457int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458{
Willy Tarreau058e9072009-07-20 09:30:05 +0200459 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200460 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461
462 if (!strcmp(args[0], "global")) { /* new section */
463 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200464 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200465 }
466 else if (!strcmp(args[0], "daemon")) {
467 global.mode |= MODE_DAEMON;
468 }
469 else if (!strcmp(args[0], "debug")) {
470 global.mode |= MODE_DEBUG;
471 }
472 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100473 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200475 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100476 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200477 }
478 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100479 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200481 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100482 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100484 else if (!strcmp(args[0], "nosplice")) {
485 global.tune.options &= ~GTUNE_USE_SPLICE;
486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200487 else if (!strcmp(args[0], "quiet")) {
488 global.mode |= MODE_QUIET;
489 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200490 else if (!strcmp(args[0], "tune.maxpollevents")) {
491 if (global.tune.maxpollevents != 0) {
492 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200493 err_code |= ERR_ALERT;
494 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200495 }
496 if (*(args[1]) == 0) {
497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200498 err_code |= ERR_ALERT | ERR_FATAL;
499 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200500 }
501 global.tune.maxpollevents = atol(args[1]);
502 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100503 else if (!strcmp(args[0], "tune.maxaccept")) {
504 if (global.tune.maxaccept != 0) {
505 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200506 err_code |= ERR_ALERT;
507 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100508 }
509 if (*(args[1]) == 0) {
510 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200511 err_code |= ERR_ALERT | ERR_FATAL;
512 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100513 }
514 global.tune.maxaccept = atol(args[1]);
515 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200516 else if (!strcmp(args[0], "tune.chksize")) {
517 if (*(args[1]) == 0) {
518 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
519 err_code |= ERR_ALERT | ERR_FATAL;
520 goto out;
521 }
522 global.tune.chksize = atol(args[1]);
523 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200524 else if (!strcmp(args[0], "tune.bufsize")) {
525 if (*(args[1]) == 0) {
526 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
527 err_code |= ERR_ALERT | ERR_FATAL;
528 goto out;
529 }
530 global.tune.bufsize = atol(args[1]);
531 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
532 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200533 trashlen = global.tune.bufsize;
534 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200535 }
536 else if (!strcmp(args[0], "tune.maxrewrite")) {
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
541 }
542 global.tune.maxrewrite = atol(args[1]);
543 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
544 global.tune.maxrewrite = global.tune.bufsize / 2;
545 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100546 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
547 if (global.tune.client_rcvbuf != 0) {
548 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
549 err_code |= ERR_ALERT;
550 goto out;
551 }
552 if (*(args[1]) == 0) {
553 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT | ERR_FATAL;
555 goto out;
556 }
557 global.tune.client_rcvbuf = atol(args[1]);
558 }
559 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
560 if (global.tune.server_rcvbuf != 0) {
561 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
562 err_code |= ERR_ALERT;
563 goto out;
564 }
565 if (*(args[1]) == 0) {
566 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
567 err_code |= ERR_ALERT | ERR_FATAL;
568 goto out;
569 }
570 global.tune.server_rcvbuf = atol(args[1]);
571 }
572 else if (!strcmp(args[0], "tune.sndbuf.client")) {
573 if (global.tune.client_sndbuf != 0) {
574 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
575 err_code |= ERR_ALERT;
576 goto out;
577 }
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583 global.tune.client_sndbuf = atol(args[1]);
584 }
585 else if (!strcmp(args[0], "tune.sndbuf.server")) {
586 if (global.tune.server_sndbuf != 0) {
587 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
588 err_code |= ERR_ALERT;
589 goto out;
590 }
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.tune.server_sndbuf = atol(args[1]);
597 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200598 else if (!strcmp(args[0], "tune.pipesize")) {
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.tune.pipesize = atol(args[1]);
605 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200606 else if (!strcmp(args[0], "tune.http.maxhdr")) {
607 if (*(args[1]) == 0) {
608 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 global.tune.max_http_hdr = atol(args[1]);
613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200614 else if (!strcmp(args[0], "uid")) {
615 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200616 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200617 err_code |= ERR_ALERT;
618 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624 }
625 global.uid = atol(args[1]);
626 }
627 else if (!strcmp(args[0], "gid")) {
628 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200629 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200630 err_code |= ERR_ALERT;
631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 }
633 if (*(args[1]) == 0) {
634 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 }
638 global.gid = atol(args[1]);
639 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200640 /* user/group name handling */
641 else if (!strcmp(args[0], "user")) {
642 struct passwd *ha_user;
643 if (global.uid != 0) {
644 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200645 err_code |= ERR_ALERT;
646 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200647 }
648 errno = 0;
649 ha_user = getpwnam(args[1]);
650 if (ha_user != NULL) {
651 global.uid = (int)ha_user->pw_uid;
652 }
653 else {
654 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 +0200655 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200656 }
657 }
658 else if (!strcmp(args[0], "group")) {
659 struct group *ha_group;
660 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200661 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200662 err_code |= ERR_ALERT;
663 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200664 }
665 errno = 0;
666 ha_group = getgrnam(args[1]);
667 if (ha_group != NULL) {
668 global.gid = (int)ha_group->gr_gid;
669 }
670 else {
671 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 +0200672 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200673 }
674 }
675 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200676 else if (!strcmp(args[0], "nbproc")) {
677 if (global.nbproc != 0) {
678 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200679 err_code |= ERR_ALERT;
680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200681 }
682 if (*(args[1]) == 0) {
683 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200684 err_code |= ERR_ALERT | ERR_FATAL;
685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200686 }
687 global.nbproc = atol(args[1]);
688 }
689 else if (!strcmp(args[0], "maxconn")) {
690 if (global.maxconn != 0) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200699 }
700 global.maxconn = atol(args[1]);
701#ifdef SYSTEM_MAXCONN
702 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
703 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);
704 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200705 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200706 }
707#endif /* SYSTEM_MAXCONN */
708 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200709 else if (!strcmp(args[0], "maxconnrate")) {
710 if (global.cps_lim != 0) {
711 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT;
713 goto out;
714 }
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.cps_lim = atol(args[1]);
721 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100722 else if (!strcmp(args[0], "maxpipes")) {
723 if (global.maxpipes != 0) {
724 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200725 err_code |= ERR_ALERT;
726 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100727 }
728 if (*(args[1]) == 0) {
729 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100732 }
733 global.maxpipes = atol(args[1]);
734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200735 else if (!strcmp(args[0], "ulimit-n")) {
736 if (global.rlimit_nofile != 0) {
737 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200738 err_code |= ERR_ALERT;
739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200740 }
741 if (*(args[1]) == 0) {
742 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200743 err_code |= ERR_ALERT | ERR_FATAL;
744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200745 }
746 global.rlimit_nofile = atol(args[1]);
747 }
748 else if (!strcmp(args[0], "chroot")) {
749 if (global.chroot != NULL) {
750 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200751 err_code |= ERR_ALERT;
752 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200753 }
754 if (*(args[1]) == 0) {
755 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200756 err_code |= ERR_ALERT | ERR_FATAL;
757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200758 }
759 global.chroot = strdup(args[1]);
760 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200761 else if (!strcmp(args[0], "description")) {
762 int i, len=0;
763 char *d;
764
765 if (!*args[1]) {
766 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
767 file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771
772 for(i=1; *args[i]; i++)
773 len += strlen(args[i])+1;
774
775 if (global.desc)
776 free(global.desc);
777
778 global.desc = d = (char *)calloc(1, len);
779
780 d += sprintf(d, "%s", args[1]);
781 for(i=2; *args[i]; i++)
782 d += sprintf(d, " %s", args[i]);
783 }
784 else if (!strcmp(args[0], "node")) {
785 int i;
786 char c;
787
788 for (i=0; args[1][i]; i++) {
789 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100790 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
791 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200792 break;
793 }
794
795 if (!i || args[1][i]) {
796 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
797 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802
803 if (global.node)
804 free(global.node);
805
806 global.node = strdup(args[1]);
807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200808 else if (!strcmp(args[0], "pidfile")) {
809 if (global.pidfile != NULL) {
810 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200811 err_code |= ERR_ALERT;
812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200813 }
814 if (*(args[1]) == 0) {
815 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200816 err_code |= ERR_ALERT | ERR_FATAL;
817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200818 }
819 global.pidfile = strdup(args[1]);
820 }
Emeric Bruned760922010-10-22 17:59:25 +0200821 else if (!strcmp(args[0], "unix-bind")) {
822 int cur_arg = 1;
823 while (*(args[cur_arg])) {
824 if (!strcmp(args[cur_arg], "prefix")) {
825 if (global.unix_bind.prefix != NULL) {
826 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
827 err_code |= ERR_ALERT;
828 cur_arg += 2;
829 continue;
830 }
831
832 if (*(args[cur_arg+1]) == 0) {
833 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837 global.unix_bind.prefix = strdup(args[cur_arg+1]);
838 cur_arg += 2;
839 continue;
840 }
841
842 if (!strcmp(args[cur_arg], "mode")) {
843
844 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
845 cur_arg += 2;
846 continue;
847 }
848
849 if (!strcmp(args[cur_arg], "uid")) {
850
851 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
852 cur_arg += 2;
853 continue;
854 }
855
856 if (!strcmp(args[cur_arg], "gid")) {
857
858 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
859 cur_arg += 2;
860 continue;
861 }
862
863 if (!strcmp(args[cur_arg], "user")) {
864 struct passwd *user;
865
866 user = getpwnam(args[cur_arg + 1]);
867 if (!user) {
868 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
869 file, linenum, args[0], args[cur_arg + 1 ]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873
874 global.unix_bind.ux.uid = user->pw_uid;
875 cur_arg += 2;
876 continue;
877 }
878
879 if (!strcmp(args[cur_arg], "group")) {
880 struct group *group;
881
882 group = getgrnam(args[cur_arg + 1]);
883 if (!group) {
884 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
885 file, linenum, args[0], args[cur_arg + 1 ]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889
890 global.unix_bind.ux.gid = group->gr_gid;
891 cur_arg += 2;
892 continue;
893 }
894
Willy Tarreaub48f9582011-09-05 01:17:06 +0200895 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200896 file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899 }
900 }
William Lallemand0f99e342011-10-12 17:50:54 +0200901 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
902 /* delete previous herited or defined syslog servers */
903 struct logsrv *back;
904 struct logsrv *tmp;
905
906 if (*(args[1]) != 0) {
907 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
908 err_code |= ERR_ALERT | ERR_FATAL;
909 goto out;
910 }
911
912 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
913 LIST_DEL(&tmp->list);
914 free(tmp);
915 }
916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200918 struct logsrv *logsrv;
919
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 if (*(args[1]) == 0 || *(args[2]) == 0) {
921 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200922 err_code |= ERR_ALERT | ERR_FATAL;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
William Lallemand0f99e342011-10-12 17:50:54 +0200925
926 logsrv = calloc(1, sizeof(struct logsrv));
927
928 logsrv->facility = get_log_facility(args[2]);
929 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200931 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200932 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 }
934
William Lallemand0f99e342011-10-12 17:50:54 +0200935 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200937 logsrv->level = get_log_level(args[3]);
938 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 }
943 }
944
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200946 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200947 logsrv->minlvl = get_log_level(args[4]);
948 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200949 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200950 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200951 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200952 }
953 }
954
Robert Tsai81ae1952007-12-05 10:47:29 +0100955 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100956 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100957 if (!sk) {
958 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100959 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100960 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200961 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100962 goto out;
963 }
William Lallemand0f99e342011-10-12 17:50:54 +0200964 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100965 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100966 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100967 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100968 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
969 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200970 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100971 goto out;
972 }
William Lallemand0f99e342011-10-12 17:50:54 +0200973 logsrv->addr = *sk;
974 if (!get_host_port(&logsrv->addr))
975 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977
William Lallemand0f99e342011-10-12 17:50:54 +0200978 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200979 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100980 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
981 char *name;
982 int len;
983
984 if (global.log_send_hostname != NULL) {
985 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
986 err_code |= ERR_ALERT;
987 goto out;
988 }
989
990 if (*(args[1]))
991 name = args[1];
992 else
993 name = hostname;
994
995 len = strlen(name);
996
997 /* We'll add a space after the name to respect the log format */
998 free(global.log_send_hostname);
999 global.log_send_hostname = malloc(len + 2);
1000 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1001 }
Kevinm48936af2010-12-22 16:08:21 +00001002 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1003 if (*(args[1]) == 0) {
1004 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1005 err_code |= ERR_ALERT | ERR_FATAL;
1006 goto out;
1007 }
1008 free(global.log_tag);
1009 global.log_tag = strdup(args[1]);
1010 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001011 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1012 if (global.spread_checks != 0) {
1013 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001014 err_code |= ERR_ALERT;
1015 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001016 }
1017 if (*(args[1]) == 0) {
1018 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001021 }
1022 global.spread_checks = atol(args[1]);
1023 if (global.spread_checks < 0 || global.spread_checks > 50) {
1024 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001025 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001027 }
1028 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001029 struct cfg_kw_list *kwl;
1030 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001031 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001032
1033 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1034 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1035 if (kwl->kw[index].section != CFG_GLOBAL)
1036 continue;
1037 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1038 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001039 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001040 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001041 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001042 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001043 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001045 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001046 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001047 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001048 err_code |= ERR_WARN;
1049 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001050 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001052 }
1053 }
1054 }
1055
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001057 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001059
Willy Tarreau058e9072009-07-20 09:30:05 +02001060 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001061 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001062 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063}
1064
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001065void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001066{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001067 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 defproxy.mode = PR_MODE_TCP;
1069 defproxy.state = PR_STNEW;
1070 defproxy.maxconn = cfg_maxpconn;
1071 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001072
1073 defproxy.defsrv.inter = DEF_CHKINTR;
1074 defproxy.defsrv.fastinter = 0;
1075 defproxy.defsrv.downinter = 0;
1076 defproxy.defsrv.rise = DEF_RISETIME;
1077 defproxy.defsrv.fall = DEF_FALLTIME;
1078 defproxy.defsrv.check_port = 0;
1079 defproxy.defsrv.maxqueue = 0;
1080 defproxy.defsrv.minconn = 0;
1081 defproxy.defsrv.maxconn = 0;
1082 defproxy.defsrv.slowstart = 0;
1083 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1084 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1085 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086}
1087
Willy Tarreauade5ec42010-01-28 19:33:49 +01001088
1089static int create_cond_regex_rule(const char *file, int line,
1090 struct proxy *px, int dir, int action, int flags,
1091 const char *cmd, const char *reg, const char *repl,
1092 const char **cond_start)
1093{
1094 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001095 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001096 const char *err;
1097 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001098 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001099
1100 if (px == &defproxy) {
1101 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto err;
1104 }
1105
1106 if (*reg == 0) {
1107 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1108 err_code |= ERR_ALERT | ERR_FATAL;
1109 goto err;
1110 }
1111
1112 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1113 err_code |= ERR_WARN;
1114
Willy Tarreau5321c422010-01-28 20:35:13 +01001115 if (cond_start &&
1116 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001117 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1118 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1119 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto err;
1122 }
1123 }
1124 else if (cond_start && **cond_start) {
1125 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1126 file, line, cmd, *cond_start);
1127 err_code |= ERR_ALERT | ERR_FATAL;
1128 goto err;
1129 }
1130
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001131 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001132 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001133 else
1134 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001135
Willy Tarreauade5ec42010-01-28 19:33:49 +01001136 preg = calloc(1, sizeof(regex_t));
1137 if (!preg) {
1138 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1139 err_code = ERR_ALERT | ERR_FATAL;
1140 goto err;
1141 }
1142
1143 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1144 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1145 err_code = ERR_ALERT | ERR_FATAL;
1146 goto err;
1147 }
1148
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001149 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001150 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 if (repl && err) {
1152 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1153 file, line, cmd, *err);
1154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto err;
1156 }
1157
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001158 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001159 err_code |= ERR_WARN;
1160
Willy Tarreauf4068b62012-05-08 17:37:49 +02001161 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001162 return err_code;
1163 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001164 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001165 free(preg);
1166 return err_code;
1167}
1168
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001170 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001171 * Returns the error code, 0 if OK, or any combination of :
1172 * - ERR_ABORT: must abort ASAP
1173 * - ERR_FATAL: we can continue parsing but not start the service
1174 * - ERR_WARN: a warning has been emitted
1175 * - ERR_ALERT: an alert has been emitted
1176 * Only the two first ones can stop processing, the two others are just
1177 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001178 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001179int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1180{
1181 static struct peers *curpeers = NULL;
1182 struct peer *newpeer = NULL;
1183 const char *err;
1184 int err_code = 0;
1185
1186 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1187
1188 err = invalid_char(args[1]);
1189 if (err) {
1190 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1191 file, linenum, *err, args[0], args[1]);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 }
1194
1195 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1196 /*
1197 * If there are two proxies with the same name only following
1198 * combinations are allowed:
1199 */
1200 if (strcmp(curpeers->id, args[1]) == 0) {
1201 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1202 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1203 err_code |= ERR_WARN;
1204 }
1205 }
1206
1207 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1209 err_code |= ERR_ALERT | ERR_ABORT;
1210 goto out;
1211 }
1212
1213 curpeers->next = peers;
1214 peers = curpeers;
1215 curpeers->conf.file = file;
1216 curpeers->conf.line = linenum;
1217 curpeers->last_change = now.tv_sec;
1218 curpeers->id = strdup(args[1]);
1219 }
1220 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1221 char *rport, *raddr;
1222 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001223 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001224
1225 if (!*args[2]) {
1226 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1227 file, linenum, args[0]);
1228 err_code |= ERR_ALERT | ERR_FATAL;
1229 goto out;
1230 }
1231
1232 err = invalid_char(args[1]);
1233 if (err) {
1234 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1235 file, linenum, *err, args[1]);
1236 err_code |= ERR_ALERT | ERR_FATAL;
1237 goto out;
1238 }
1239
1240 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1242 err_code |= ERR_ALERT | ERR_ABORT;
1243 goto out;
1244 }
1245
1246 /* the peers are linked backwards first */
1247 curpeers->count++;
1248 newpeer->next = curpeers->remote;
1249 curpeers->remote = newpeer;
1250 newpeer->peers = curpeers;
1251 newpeer->conf.file = file;
1252 newpeer->conf.line = linenum;
1253
1254 newpeer->last_change = now.tv_sec;
1255 newpeer->id = strdup(args[1]);
1256
1257 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001258 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001259 if (rport) {
1260 *rport++ = 0;
1261 realport = atol(rport);
1262 }
1263 if (!realport) {
1264 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
1267 }
1268
Willy Tarreaufab5a432011-03-04 15:31:53 +01001269 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001270 free(raddr);
1271 if (!sk) {
1272 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
1275 }
1276 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001277 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02001278 newpeer->sock = &sock_raw;
1279 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001280
1281 if (!sk) {
1282 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1283 file, linenum, newpeer->addr.ss_family, args[2]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001288 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001289
1290 if (strcmp(newpeer->id, localpeer) == 0) {
1291 /* Current is local peer, it define a frontend */
1292 newpeer->local = 1;
1293
1294 if (!curpeers->peers_fe) {
1295 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1296 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1297 err_code |= ERR_ALERT | ERR_ABORT;
1298 goto out;
1299 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001300
Willy Tarreau237250c2011-07-29 01:49:03 +02001301 init_new_proxy(curpeers->peers_fe);
1302 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001303
1304 curpeers->peers_fe->last_change = now.tv_sec;
1305 curpeers->peers_fe->id = strdup(args[1]);
1306 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001307 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001308 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1309 curpeers->peers_fe->timeout.connect = 5000;
1310 curpeers->peers_fe->accept = peer_accept;
1311 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001312 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001313 err_code |= ERR_FATAL;
1314 goto out;
1315 }
1316 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1317 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1318 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1319 curpeers->peers_fe->listen->accept = session_accept;
1320 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1321 curpeers->peers_fe->listen->handler = process_session;
1322 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001323 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1324 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001325 }
1326 }
1327 } /* neither "peer" nor "peers" */
1328 else if (*args[0] != 0) {
1329 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
1334out:
1335 return err_code;
1336}
1337
1338
Willy Tarreau3842f002009-06-14 11:39:52 +02001339int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001340{
1341 static struct proxy *curproxy = NULL;
1342 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001343 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001344 int rc;
1345 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001346 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001347 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001348 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001349 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350
Willy Tarreau977b8e42006-12-29 14:19:17 +01001351 if (!strcmp(args[0], "listen"))
1352 rc = PR_CAP_LISTEN;
1353 else if (!strcmp(args[0], "frontend"))
1354 rc = PR_CAP_FE | PR_CAP_RS;
1355 else if (!strcmp(args[0], "backend"))
1356 rc = PR_CAP_BE | PR_CAP_RS;
1357 else if (!strcmp(args[0], "ruleset"))
1358 rc = PR_CAP_RS;
1359 else
1360 rc = PR_CAP_NONE;
1361
1362 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 if (!*args[1]) {
1364 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1365 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1366 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001367 err_code |= ERR_ALERT | ERR_ABORT;
1368 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001369 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001370
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001371 err = invalid_char(args[1]);
1372 if (err) {
1373 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1374 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001375 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001376 }
1377
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001378 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1379 /*
1380 * If there are two proxies with the same name only following
1381 * combinations are allowed:
1382 *
1383 * listen backend frontend ruleset
1384 * listen - - - -
1385 * backend - - OK -
1386 * frontend - OK - -
1387 * ruleset - - - -
1388 */
1389
1390 if (!strcmp(curproxy->id, args[1]) &&
1391 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1392 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001393 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1394 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1395 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001396 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001397 }
1398 }
1399
Willy Tarreaubaaee002006-06-26 02:48:02 +02001400 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1401 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001402 err_code |= ERR_ALERT | ERR_ABORT;
1403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001404 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001405
Willy Tarreau97cb7802010-01-03 20:23:58 +01001406 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001407 curproxy->next = proxy;
1408 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001409 curproxy->conf.file = file;
1410 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001411 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001412 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001413 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414
1415 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001416 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001417 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001418 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001419 err_code |= ERR_FATAL;
1420 goto out;
1421 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001422 new = curproxy->listen;
1423 while (new != last) {
1424 new->conf.file = file;
1425 new->conf.line = linenum;
1426 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001427 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001429 }
1430
1431 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001432 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001433 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001434
Willy Tarreaubaaee002006-06-26 02:48:02 +02001435 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001437 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001438 curproxy->no_options = defproxy.no_options;
1439 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001440 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001441 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001442 curproxy->except_net = defproxy.except_net;
1443 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001444 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001445 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001447 if (defproxy.fwdfor_hdr_len) {
1448 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1449 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1450 }
1451
Willy Tarreaub86db342009-11-30 11:50:16 +01001452 if (defproxy.orgto_hdr_len) {
1453 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1454 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1455 }
1456
Mark Lamourinec2247f02012-01-04 13:02:01 -05001457 if (defproxy.server_id_hdr_len) {
1458 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1459 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1460 }
1461
Willy Tarreau977b8e42006-12-29 14:19:17 +01001462 if (curproxy->cap & PR_CAP_FE) {
1463 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001464 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001465 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001466
1467 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001468 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1469 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001470
1471 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473
Willy Tarreau977b8e42006-12-29 14:19:17 +01001474 if (curproxy->cap & PR_CAP_BE) {
1475 curproxy->fullconn = defproxy.fullconn;
1476 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001478 if (defproxy.check_req) {
1479 curproxy->check_req = calloc(1, defproxy.check_len);
1480 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1481 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001482 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001484 if (defproxy.expect_str) {
1485 curproxy->expect_str = strdup(defproxy.expect_str);
1486 if (defproxy.expect_regex) {
1487 /* note: this regex is known to be valid */
1488 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1489 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1490 }
1491 }
1492
Willy Tarreau67402132012-05-31 20:40:20 +02001493 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001494 if (defproxy.cookie_name)
1495 curproxy->cookie_name = strdup(defproxy.cookie_name);
1496 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001497 if (defproxy.cookie_domain)
1498 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001499
Willy Tarreau31936852010-10-06 16:59:56 +02001500 if (defproxy.cookie_maxidle)
1501 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1502
1503 if (defproxy.cookie_maxlife)
1504 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1505
Emeric Brun647caf12009-06-30 17:57:00 +02001506 if (defproxy.rdp_cookie_name)
1507 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1508 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1509
Willy Tarreau01732802007-11-01 22:48:15 +01001510 if (defproxy.url_param_name)
1511 curproxy->url_param_name = strdup(defproxy.url_param_name);
1512 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001513
Benoitaffb4812009-03-25 13:02:10 +01001514 if (defproxy.hh_name)
1515 curproxy->hh_name = strdup(defproxy.hh_name);
1516 curproxy->hh_len = defproxy.hh_len;
1517 curproxy->hh_match_domain = defproxy.hh_match_domain;
1518
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001519 if (defproxy.iface_name)
1520 curproxy->iface_name = strdup(defproxy.iface_name);
1521 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001524 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001525 if (defproxy.capture_name)
1526 curproxy->capture_name = strdup(defproxy.capture_name);
1527 curproxy->capture_namelen = defproxy.capture_namelen;
1528 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530
Willy Tarreau977b8e42006-12-29 14:19:17 +01001531 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001532 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001533 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001534 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001535 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001536 curproxy->uri_auth = defproxy.uri_auth;
1537 curproxy->mon_net = defproxy.mon_net;
1538 curproxy->mon_mask = defproxy.mon_mask;
1539 if (defproxy.monitor_uri)
1540 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1541 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001542 if (defproxy.defbe.name)
1543 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001544
1545 /* get either a pointer to the logformat string or a copy of it */
1546 curproxy->logformat_string = defproxy.logformat_string;
1547 if (curproxy->logformat_string &&
1548 curproxy->logformat_string != default_http_log_format &&
1549 curproxy->logformat_string != default_tcp_log_format &&
1550 curproxy->logformat_string != clf_http_log_format)
1551 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001552 }
1553
1554 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001555 curproxy->timeout.connect = defproxy.timeout.connect;
1556 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001557 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001558 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001559 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001560 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001561 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001562 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001563 curproxy->source_addr = defproxy.source_addr;
1564 }
1565
Willy Tarreaubaaee002006-06-26 02:48:02 +02001566 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001567
1568 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001569 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001570 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001571 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001572 LIST_INIT(&node->list);
1573 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1574 }
1575
Willy Tarreau196729e2012-05-31 19:30:26 +02001576 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1577 if (curproxy->uniqueid_format_string)
1578 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001579
1580 /* copy default header unique id */
1581 if (defproxy.header_unique_id)
1582 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1583
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001585 curproxy->conf.used_listener_id = EB_ROOT;
1586 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001587
Willy Tarreau93893792009-07-23 13:19:11 +02001588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 }
1590 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1591 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001592 /* FIXME-20070101: we should do this too at the end of the
1593 * config parsing to free all default values.
1594 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001595 free(defproxy.check_req);
1596 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001597 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001598 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001599 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001600 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001601 free(defproxy.capture_name);
1602 free(defproxy.monitor_uri);
1603 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001604 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001605 free(defproxy.fwdfor_hdr_name);
1606 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001607 free(defproxy.orgto_hdr_name);
1608 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001609 free(defproxy.server_id_hdr_name);
1610 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001611 free(defproxy.expect_str);
1612 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001613
Willy Tarreau39b06652012-06-01 10:58:06 +02001614 if (defproxy.logformat_string != default_http_log_format &&
1615 defproxy.logformat_string != default_tcp_log_format &&
1616 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001617 free(defproxy.logformat_string);
1618
1619 free(defproxy.uniqueid_format_string);
1620
Willy Tarreaua534fea2008-08-03 12:19:50 +02001621 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001622 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001623
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 /* we cannot free uri_auth because it might already be used */
1625 init_default_instance();
1626 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001627 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 }
1630 else if (curproxy == NULL) {
1631 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001632 err_code |= ERR_ALERT | ERR_FATAL;
1633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 }
1635
Willy Tarreau977b8e42006-12-29 14:19:17 +01001636
1637 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001639 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001640 int cur_arg;
1641
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 if (curproxy == &defproxy) {
1643 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001644 err_code |= ERR_ALERT | ERR_FATAL;
1645 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001647 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001648 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649
Emeric Bruned760922010-10-22 17:59:25 +02001650 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001651 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001653 err_code |= ERR_ALERT | ERR_FATAL;
1654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001656
1657 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001658
1659 /* NOTE: the following line might create several listeners if there
1660 * are comma-separated IPs or port ranges. So all further processing
1661 * will have to be applied to all listeners created after last_listen.
1662 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001663 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001664 err_code |= ERR_ALERT | ERR_FATAL;
1665 goto out;
1666 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001667
Willy Tarreau90a570f2009-10-04 20:54:54 +02001668 new_listen = curproxy->listen;
1669 while (new_listen != last_listen) {
1670 new_listen->conf.file = file;
1671 new_listen->conf.line = linenum;
1672 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001673 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001674 }
1675
Emeric Bruned760922010-10-22 17:59:25 +02001676 /* Set default global rights and owner for unix bind */
1677 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1678 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1679 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001680 cur_arg = 2;
1681 while (*(args[cur_arg])) {
1682 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1683#ifdef SO_BINDTODEVICE
1684 struct listener *l;
1685
Emeric Bruned760922010-10-22 17:59:25 +02001686 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1687 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1688 file, linenum, args[0], args[cur_arg]);
1689 err_code |= ERR_ALERT | ERR_FATAL;
1690 goto out;
1691 }
1692
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001693 if (!*args[cur_arg + 1]) {
1694 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1695 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001696 err_code |= ERR_ALERT | ERR_FATAL;
1697 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001698 }
1699
1700 for (l = curproxy->listen; l != last_listen; l = l->next)
1701 l->interface = strdup(args[cur_arg + 1]);
1702
1703 global.last_checks |= LSTCHK_NETADM;
1704
1705 cur_arg += 2;
1706 continue;
1707#else
1708 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1709 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_ALERT | ERR_FATAL;
1711 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001712#endif
1713 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001714 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1715#ifdef TCP_MAXSEG
1716 struct listener *l;
1717 int mss;
1718
Emeric Bruned760922010-10-22 17:59:25 +02001719 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1720 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1721 file, linenum, args[0], args[cur_arg]);
1722 err_code |= ERR_ALERT | ERR_FATAL;
1723 goto out;
1724 }
1725
Willy Tarreaube1b9182009-06-14 18:48:19 +02001726 if (!*args[cur_arg + 1]) {
1727 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1728 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001729 err_code |= ERR_ALERT | ERR_FATAL;
1730 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001731 }
1732
Willy Tarreau48a7e722010-12-24 15:26:39 +01001733 mss = atoi(args[cur_arg + 1]);
1734 if (!mss || abs(mss) > 65535) {
1735 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001736 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001737 err_code |= ERR_ALERT | ERR_FATAL;
1738 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001739 }
1740
1741 for (l = curproxy->listen; l != last_listen; l = l->next)
1742 l->maxseg = mss;
1743
1744 cur_arg += 2;
1745 continue;
1746#else
1747 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1748 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001749 err_code |= ERR_ALERT | ERR_FATAL;
1750 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001751#endif
1752 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001753
1754 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1755#ifdef TCP_DEFER_ACCEPT
1756 struct listener *l;
1757
1758 for (l = curproxy->listen; l != last_listen; l = l->next)
1759 l->options |= LI_O_DEF_ACCEPT;
1760
1761 cur_arg ++;
1762 continue;
1763#else
1764 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1765 file, linenum, args[0], args[cur_arg]);
1766 err_code |= ERR_ALERT | ERR_FATAL;
1767 goto out;
1768#endif
1769 }
1770
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001771 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001772#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001773 struct listener *l;
1774
Emeric Bruned760922010-10-22 17:59:25 +02001775 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1776 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1777 file, linenum, args[0], args[cur_arg]);
1778 err_code |= ERR_ALERT | ERR_FATAL;
1779 goto out;
1780 }
1781
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001782 for (l = curproxy->listen; l != last_listen; l = l->next)
1783 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001784
1785 cur_arg ++;
1786 continue;
1787#else
1788 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1789 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
1791 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001792#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001793 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001794
Willy Tarreau8a956912010-10-15 14:27:08 +02001795 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1796 struct listener *l;
1797
1798 for (l = curproxy->listen; l != last_listen; l = l->next)
1799 l->options |= LI_O_ACC_PROXY;
1800
1801 cur_arg ++;
1802 continue;
1803 }
1804
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001805 if (!strcmp(args[cur_arg], "name")) {
1806 struct listener *l;
1807
1808 for (l = curproxy->listen; l != last_listen; l = l->next)
1809 l->name = strdup(args[cur_arg + 1]);
1810
1811 cur_arg += 2;
1812 continue;
1813 }
1814
1815 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001816 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001817 struct listener *l;
1818
1819 if (curproxy->listen->next != last_listen) {
1820 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1821 file, linenum, args[cur_arg]);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825
1826 if (!*args[cur_arg + 1]) {
1827 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1828 file, linenum, args[cur_arg]);
1829 err_code |= ERR_ALERT | ERR_FATAL;
1830 goto out;
1831 }
1832
1833 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001834 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001835
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001836 if (curproxy->listen->luid <= 0) {
1837 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001838 file, linenum);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001843 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1844 if (node) {
1845 l = container_of(node, struct listener, conf.id);
1846 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1847 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
1851 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1852
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001853 cur_arg += 2;
1854 continue;
1855 }
1856
Emeric Bruned760922010-10-22 17:59:25 +02001857 if (!strcmp(args[cur_arg], "mode")) {
1858
1859 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1860 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1861 file, linenum, args[0], args[cur_arg]);
1862 err_code |= ERR_ALERT | ERR_FATAL;
1863 goto out;
1864 }
1865
1866 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1867
1868 cur_arg += 2;
1869 continue;
1870 }
1871
1872 if (!strcmp(args[cur_arg], "uid")) {
1873
1874 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1875 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1876 file, linenum, args[0], args[cur_arg]);
1877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
1879 }
1880
1881 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1882 cur_arg += 2;
1883 continue;
1884 }
1885
1886 if (!strcmp(args[cur_arg], "gid")) {
1887
1888 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1889 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1890 file, linenum, args[0], args[cur_arg]);
1891 err_code |= ERR_ALERT | ERR_FATAL;
1892 goto out;
1893 }
1894
1895 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1896 cur_arg += 2;
1897 continue;
1898 }
1899
1900 if (!strcmp(args[cur_arg], "user")) {
1901 struct passwd *user;
1902
1903 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1904 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1905 file, linenum, args[0], args[cur_arg]);
1906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
1908 }
1909 user = getpwnam(args[cur_arg + 1]);
1910 if (!user) {
1911 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1912 file, linenum, args[0], args[cur_arg + 1 ]);
1913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
1915 }
1916
1917 curproxy->listen->perm.ux.uid = user->pw_uid;
1918 cur_arg += 2;
1919 continue;
1920 }
1921
1922 if (!strcmp(args[cur_arg], "group")) {
1923 struct group *group;
1924
1925 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1926 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1927 file, linenum, args[0], args[cur_arg]);
1928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
1930 }
1931 group = getgrnam(args[cur_arg + 1]);
1932 if (!group) {
1933 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1934 file, linenum, args[0], args[cur_arg + 1 ]);
1935 err_code |= ERR_ALERT | ERR_FATAL;
1936 goto out;
1937 }
1938
1939 curproxy->listen->perm.ux.gid = group->gr_gid;
1940 cur_arg += 2;
1941 continue;
1942 }
1943
Willy Tarreaub48f9582011-09-05 01:17:06 +02001944 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 +01001945 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001948 }
Willy Tarreau93893792009-07-23 13:19:11 +02001949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950 }
1951 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1952 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1953 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1954 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001955 err_code |= ERR_ALERT | ERR_FATAL;
1956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001959 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001960
Willy Tarreaubaaee002006-06-26 02:48:02 +02001961 /* flush useless bits */
1962 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001964 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001965 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001966 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001968
Willy Tarreau1c47f852006-07-09 08:22:27 +02001969 if (!*args[1]) {
1970 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1971 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001972 err_code |= ERR_ALERT | ERR_FATAL;
1973 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001974 }
1975
Willy Tarreaua534fea2008-08-03 12:19:50 +02001976 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001977 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001978 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001979 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001980 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1981
Willy Tarreau93893792009-07-23 13:19:11 +02001982 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001983 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1985 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1986 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1987 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1988 else {
1989 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 }
1993 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001994 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001995 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001996
1997 if (curproxy == &defproxy) {
1998 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1999 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002000 err_code |= ERR_ALERT | ERR_FATAL;
2001 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002002 }
2003
2004 if (!*args[1]) {
2005 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2006 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002007 err_code |= ERR_ALERT | ERR_FATAL;
2008 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002009 }
2010
2011 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002012 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002013
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002014 if (curproxy->uuid <= 0) {
2015 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002016 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
2018 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002019 }
2020
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002021 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2022 if (node) {
2023 struct proxy *target = container_of(node, struct proxy, conf.id);
2024 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2025 file, linenum, proxy_type_str(curproxy), curproxy->id,
2026 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
2029 }
2030 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002031 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002032 else if (!strcmp(args[0], "description")) {
2033 int i, len=0;
2034 char *d;
2035
Cyril Bonté99ed3272010-01-24 23:29:44 +01002036 if (curproxy == &defproxy) {
2037 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2038 file, linenum, args[0]);
2039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
2041 }
2042
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002043 if (!*args[1]) {
2044 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2045 file, linenum, args[0]);
2046 return -1;
2047 }
2048
2049 for(i=1; *args[i]; i++)
2050 len += strlen(args[i])+1;
2051
2052 d = (char *)calloc(1, len);
2053 curproxy->desc = d;
2054
2055 d += sprintf(d, "%s", args[1]);
2056 for(i=2; *args[i]; i++)
2057 d += sprintf(d, " %s", args[i]);
2058
2059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2061 curproxy->state = PR_STSTOPPED;
2062 }
2063 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2064 curproxy->state = PR_STNEW;
2065 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002066 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2067 int cur_arg = 1;
2068 unsigned int set = 0;
2069
2070 while (*args[cur_arg]) {
2071 int u;
2072 if (strcmp(args[cur_arg], "all") == 0) {
2073 set = 0;
2074 break;
2075 }
2076 else if (strcmp(args[cur_arg], "odd") == 0) {
2077 set |= 0x55555555;
2078 }
2079 else if (strcmp(args[cur_arg], "even") == 0) {
2080 set |= 0xAAAAAAAA;
2081 }
2082 else {
2083 u = str2uic(args[cur_arg]);
2084 if (u < 1 || u > 32) {
2085 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2086 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002087 err_code |= ERR_ALERT | ERR_FATAL;
2088 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002089 }
2090 if (u > global.nbproc) {
2091 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002093 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002094 }
2095 set |= 1 << (u - 1);
2096 }
2097 cur_arg++;
2098 }
2099 curproxy->bind_proc = set;
2100 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002101 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002102 if (curproxy == &defproxy) {
2103 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002106 }
2107
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002108 err = invalid_char(args[1]);
2109 if (err) {
2110 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2111 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002112 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002113 }
2114
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002115 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2116 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2117 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002118 err_code |= ERR_ALERT | ERR_FATAL;
2119 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002120 }
2121 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002122 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2123 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002124
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002127
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 if (*(args[1]) == 0) {
2129 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002131 err_code |= ERR_ALERT | ERR_FATAL;
2132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002134
Willy Tarreau67402132012-05-31 20:40:20 +02002135 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002136 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002137 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002138 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 curproxy->cookie_name = strdup(args[1]);
2140 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002141
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142 cur_arg = 2;
2143 while (*(args[cur_arg])) {
2144 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002145 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 }
2147 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002148 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149 }
2150 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002151 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 }
2153 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002154 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 }
2156 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002157 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002158 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002159 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002160 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002161 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002162 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002163 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002164 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002165 else if (!strcmp(args[cur_arg], "httponly")) {
2166 curproxy->ck_opts |= PR_CK_HTTPONLY;
2167 }
2168 else if (!strcmp(args[cur_arg], "secure")) {
2169 curproxy->ck_opts |= PR_CK_SECURE;
2170 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002171 else if (!strcmp(args[cur_arg], "domain")) {
2172 if (!*args[cur_arg + 1]) {
2173 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2174 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002177 }
2178
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002179 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002180 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002181 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2182 " dots nor does not start with a dot."
2183 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002184 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002185 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002186 }
2187
2188 err = invalid_domainchar(args[cur_arg + 1]);
2189 if (err) {
2190 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2191 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002194 }
2195
Willy Tarreau68a897b2009-12-03 23:28:34 +01002196 if (!curproxy->cookie_domain) {
2197 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2198 } else {
2199 /* one domain was already specified, add another one by
2200 * building the string which will be returned along with
2201 * the cookie.
2202 */
2203 char *new_ptr;
2204 int new_len = strlen(curproxy->cookie_domain) +
2205 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2206 new_ptr = malloc(new_len);
2207 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2208 free(curproxy->cookie_domain);
2209 curproxy->cookie_domain = new_ptr;
2210 }
Willy Tarreau31936852010-10-06 16:59:56 +02002211 cur_arg++;
2212 }
2213 else if (!strcmp(args[cur_arg], "maxidle")) {
2214 unsigned int maxidle;
2215 const char *res;
2216
2217 if (!*args[cur_arg + 1]) {
2218 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2219 file, linenum, args[cur_arg]);
2220 err_code |= ERR_ALERT | ERR_FATAL;
2221 goto out;
2222 }
2223
2224 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2225 if (res) {
2226 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2227 file, linenum, *res, args[cur_arg]);
2228 err_code |= ERR_ALERT | ERR_FATAL;
2229 goto out;
2230 }
2231 curproxy->cookie_maxidle = maxidle;
2232 cur_arg++;
2233 }
2234 else if (!strcmp(args[cur_arg], "maxlife")) {
2235 unsigned int maxlife;
2236 const char *res;
2237
2238 if (!*args[cur_arg + 1]) {
2239 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2240 file, linenum, args[cur_arg]);
2241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
2243 }
2244
2245 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2246 if (res) {
2247 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2248 file, linenum, *res, args[cur_arg]);
2249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
2251 }
2252 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002253 cur_arg++;
2254 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002256 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 +02002257 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 }
2261 cur_arg++;
2262 }
Willy Tarreau67402132012-05-31 20:40:20 +02002263 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002264 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2265 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 }
2268
Willy Tarreau67402132012-05-31 20:40:20 +02002269 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2271 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002274
Willy Tarreau67402132012-05-31 20:40:20 +02002275 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002276 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2277 file, linenum);
2278 err_code |= ERR_ALERT | ERR_FATAL;
2279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002281 else if (!strcmp(args[0], "persist")) { /* persist */
2282 if (*(args[1]) == 0) {
2283 Alert("parsing [%s:%d] : missing persist method.\n",
2284 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002285 err_code |= ERR_ALERT | ERR_FATAL;
2286 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002287 }
2288
2289 if (!strncmp(args[1], "rdp-cookie", 10)) {
2290 curproxy->options2 |= PR_O2_RDPC_PRST;
2291
Emeric Brunb982a3d2010-01-04 15:45:53 +01002292 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002293 const char *beg, *end;
2294
2295 beg = args[1] + 11;
2296 end = strchr(beg, ')');
2297
2298 if (!end || end == beg) {
2299 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2300 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002303 }
2304
2305 free(curproxy->rdp_cookie_name);
2306 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2307 curproxy->rdp_cookie_len = end-beg;
2308 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002309 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002310 free(curproxy->rdp_cookie_name);
2311 curproxy->rdp_cookie_name = strdup("msts");
2312 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2313 }
2314 else { /* syntax */
2315 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2316 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002317 err_code |= ERR_ALERT | ERR_FATAL;
2318 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002319 }
2320 }
2321 else {
2322 Alert("parsing [%s:%d] : unknown persist method.\n",
2323 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002326 }
2327 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002329 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002331 if (curproxy == &defproxy) {
2332 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
2335 }
2336
Willy Tarreau977b8e42006-12-29 14:19:17 +01002337 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002339
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002341 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002342 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 }
2346 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002347 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 curproxy->appsession_name = strdup(args[1]);
2349 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2350 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002351 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2352 if (err) {
2353 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2354 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_ALERT | ERR_FATAL;
2356 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002357 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002358 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002359
Willy Tarreau51041c72007-09-09 21:56:53 +02002360 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2361 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_ABORT;
2363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002364 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002365
2366 cur_arg = 6;
2367 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002368 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2369 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002370 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002371 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002372 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002373 } else if (!strcmp(args[cur_arg], "prefix")) {
2374 curproxy->options2 |= PR_O2_AS_PFX;
2375 } else if (!strcmp(args[cur_arg], "mode")) {
2376 if (!*args[cur_arg + 1]) {
2377 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2378 file, linenum, args[0], args[cur_arg]);
2379 err_code |= ERR_ALERT | ERR_FATAL;
2380 goto out;
2381 }
2382
2383 cur_arg++;
2384 if (!strcmp(args[cur_arg], "query-string")) {
2385 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2386 curproxy->options2 |= PR_O2_AS_M_QS;
2387 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2388 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2389 curproxy->options2 |= PR_O2_AS_M_PP;
2390 } else {
2391 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
2394 }
2395 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002396 cur_arg++;
2397 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398 } /* Url App Session */
2399 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002400 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002401 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002402
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002404 if (curproxy == &defproxy) {
2405 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
2408 }
2409
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 if (*(args[4]) == 0) {
2411 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2412 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002413 err_code |= ERR_ALERT | ERR_FATAL;
2414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002416 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 curproxy->capture_name = strdup(args[2]);
2418 curproxy->capture_namelen = strlen(curproxy->capture_name);
2419 curproxy->capture_len = atol(args[4]);
2420 if (curproxy->capture_len >= CAPTURE_LEN) {
2421 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2422 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 curproxy->capture_len = CAPTURE_LEN - 1;
2425 }
2426 curproxy->to_log |= LW_COOKIE;
2427 }
2428 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2429 struct cap_hdr *hdr;
2430
2431 if (curproxy == &defproxy) {
2432 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 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435 }
2436
2437 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2438 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2439 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
2443
2444 hdr = calloc(sizeof(struct cap_hdr), 1);
2445 hdr->next = curproxy->req_cap;
2446 hdr->name = strdup(args[3]);
2447 hdr->namelen = strlen(args[3]);
2448 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002449 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 hdr->index = curproxy->nb_req_cap++;
2451 curproxy->req_cap = hdr;
2452 curproxy->to_log |= LW_REQHDR;
2453 }
2454 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2455 struct cap_hdr *hdr;
2456
2457 if (curproxy == &defproxy) {
2458 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 +02002459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002461 }
2462
2463 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2464 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2465 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 }
2469 hdr = calloc(sizeof(struct cap_hdr), 1);
2470 hdr->next = curproxy->rsp_cap;
2471 hdr->name = strdup(args[3]);
2472 hdr->namelen = strlen(args[3]);
2473 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002474 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 hdr->index = curproxy->nb_rsp_cap++;
2476 curproxy->rsp_cap = hdr;
2477 curproxy->to_log |= LW_RSPHDR;
2478 }
2479 else {
2480 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2481 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 }
2485 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002486 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002487 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002488 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489
Willy Tarreaubaaee002006-06-26 02:48:02 +02002490 if (*(args[1]) == 0) {
2491 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2492 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 }
2496 curproxy->conn_retries = atol(args[1]);
2497 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002498 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002499 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002500
2501 if (curproxy == &defproxy) {
2502 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506
Willy Tarreauff011f22011-01-06 17:51:27 +01002507 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 +01002508 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2509 file, linenum, args[0]);
2510 err_code |= ERR_WARN;
2511 }
2512
Willy Tarreauff011f22011-01-06 17:51:27 +01002513 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002514
Willy Tarreauff011f22011-01-06 17:51:27 +01002515 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002516 err_code |= ERR_ALERT | ERR_ABORT;
2517 goto out;
2518 }
2519
Willy Tarreauff011f22011-01-06 17:51:27 +01002520 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2521 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002522 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002523 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2524 /* set the header name and length into the proxy structure */
2525 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2526 err_code |= ERR_WARN;
2527
2528 if (!*args[1]) {
2529 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2530 file, linenum, args[0]);
2531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
2533 }
2534
2535 /* set the desired header name */
2536 free(curproxy->server_id_hdr_name);
2537 curproxy->server_id_hdr_name = strdup(args[1]);
2538 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2539 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002540 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002541 if (curproxy == &defproxy) {
2542 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002545 }
2546
Willy Tarreauef6494c2010-01-28 17:12:36 +01002547 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002548 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002552 }
2553
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002554 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2555 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2556 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002559 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002560
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002561 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002562 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002563 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002564 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002565 struct redirect_rule *rule;
2566 int cur_arg;
2567 int type = REDIRECT_TYPE_NONE;
2568 int code = 302;
2569 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002570 char *cookie = NULL;
2571 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002572 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002573
Cyril Bonté99ed3272010-01-24 23:29:44 +01002574 if (curproxy == &defproxy) {
2575 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2576 err_code |= ERR_ALERT | ERR_FATAL;
2577 goto out;
2578 }
2579
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002580 cur_arg = 1;
2581 while (*(args[cur_arg])) {
2582 if (!strcmp(args[cur_arg], "location")) {
2583 if (!*args[cur_arg + 1]) {
2584 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2585 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002588 }
2589
2590 type = REDIRECT_TYPE_LOCATION;
2591 cur_arg++;
2592 destination = args[cur_arg];
2593 }
2594 else if (!strcmp(args[cur_arg], "prefix")) {
2595 if (!*args[cur_arg + 1]) {
2596 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2597 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002598 err_code |= ERR_ALERT | ERR_FATAL;
2599 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002600 }
2601
2602 type = REDIRECT_TYPE_PREFIX;
2603 cur_arg++;
2604 destination = args[cur_arg];
2605 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002606 else if (!strcmp(args[cur_arg], "set-cookie")) {
2607 if (!*args[cur_arg + 1]) {
2608 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2609 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002612 }
2613
2614 cur_arg++;
2615 cookie = args[cur_arg];
2616 cookie_set = 1;
2617 }
2618 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2619 if (!*args[cur_arg + 1]) {
2620 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2621 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002624 }
2625
2626 cur_arg++;
2627 cookie = args[cur_arg];
2628 cookie_set = 0;
2629 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002630 else if (!strcmp(args[cur_arg],"code")) {
2631 if (!*args[cur_arg + 1]) {
2632 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2633 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002636 }
2637 cur_arg++;
2638 code = atol(args[cur_arg]);
2639 if (code < 301 || code > 303) {
2640 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2641 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002644 }
2645 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002646 else if (!strcmp(args[cur_arg],"drop-query")) {
2647 flags |= REDIRECT_FLAG_DROP_QS;
2648 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002649 else if (!strcmp(args[cur_arg],"append-slash")) {
2650 flags |= REDIRECT_FLAG_APPEND_SLASH;
2651 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002652 else if (strcmp(args[cur_arg], "if") == 0 ||
2653 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002654 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002655 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002656 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2657 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002661 break;
2662 }
2663 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002664 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 +02002665 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002668 }
2669 cur_arg++;
2670 }
2671
2672 if (type == REDIRECT_TYPE_NONE) {
2673 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002677 }
2678
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002679 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2680 rule->cond = cond;
2681 rule->rdr_str = strdup(destination);
2682 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002683 if (cookie) {
2684 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002685 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002686 */
2687 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002688 if (cookie_set) {
2689 rule->cookie_str = malloc(rule->cookie_len + 10);
2690 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2691 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2692 rule->cookie_len += 9;
2693 } else {
2694 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002695 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002696 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2697 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002698 }
2699 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002700 rule->type = type;
2701 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002702 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002703 LIST_INIT(&rule->list);
2704 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002705 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2706 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002707 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002708 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002709 struct switching_rule *rule;
2710
Willy Tarreaub099aca2008-10-12 17:26:37 +02002711 if (curproxy == &defproxy) {
2712 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002715 }
2716
Willy Tarreau55ea7572007-06-17 19:56:27 +02002717 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002719
2720 if (*(args[1]) == 0) {
2721 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002724 }
2725
Willy Tarreauef6494c2010-01-28 17:12:36 +01002726 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002727 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2728 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002731 }
2732
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002733 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2734 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2735 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002738 }
2739
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002740 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002741
Willy Tarreau55ea7572007-06-17 19:56:27 +02002742 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2743 rule->cond = cond;
2744 rule->be.name = strdup(args[1]);
2745 LIST_INIT(&rule->list);
2746 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2747 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002748 else if (strcmp(args[0], "use-server") == 0) {
2749 struct server_rule *rule;
2750
2751 if (curproxy == &defproxy) {
2752 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2753 err_code |= ERR_ALERT | ERR_FATAL;
2754 goto out;
2755 }
2756
2757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2758 err_code |= ERR_WARN;
2759
2760 if (*(args[1]) == 0) {
2761 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2762 err_code |= ERR_ALERT | ERR_FATAL;
2763 goto out;
2764 }
2765
2766 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2767 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2768 file, linenum, args[0]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002773 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2774 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2775 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002776 err_code |= ERR_ALERT | ERR_FATAL;
2777 goto out;
2778 }
2779
2780 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2781
2782 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2783 rule->cond = cond;
2784 rule->srv.name = strdup(args[1]);
2785 LIST_INIT(&rule->list);
2786 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2787 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2788 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002789 else if ((!strcmp(args[0], "force-persist")) ||
2790 (!strcmp(args[0], "ignore-persist"))) {
2791 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002792
2793 if (curproxy == &defproxy) {
2794 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2795 err_code |= ERR_ALERT | ERR_FATAL;
2796 goto out;
2797 }
2798
2799 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2800 err_code |= ERR_WARN;
2801
Willy Tarreauef6494c2010-01-28 17:12:36 +01002802 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002803 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2804 file, linenum, args[0]);
2805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
2807 }
2808
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002809 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2810 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2811 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
2814 }
2815
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002816 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002817
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002818 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002819 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002820 if (!strcmp(args[0], "force-persist")) {
2821 rule->type = PERSIST_TYPE_FORCE;
2822 } else {
2823 rule->type = PERSIST_TYPE_IGNORE;
2824 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002825 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002826 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002827 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002828 else if (!strcmp(args[0], "stick-table")) {
2829 int myidx = 1;
2830
Emeric Brun32da3c42010-09-23 18:39:19 +02002831 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002832 curproxy->table.type = (unsigned int)-1;
2833 while (*args[myidx]) {
2834 const char *err;
2835
2836 if (strcmp(args[myidx], "size") == 0) {
2837 myidx++;
2838 if (!*(args[myidx])) {
2839 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2840 file, linenum, args[myidx-1]);
2841 err_code |= ERR_ALERT | ERR_FATAL;
2842 goto out;
2843 }
2844 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2845 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2846 file, linenum, *err, args[myidx-1]);
2847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
2849 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002850 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002851 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002852 else if (strcmp(args[myidx], "peers") == 0) {
2853 myidx++;
2854 if (!*(args[myidx])) {
2855 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2856 file, linenum, args[myidx-1]);
2857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
2859 }
2860 curproxy->table.peers.name = strdup(args[myidx++]);
2861 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002862 else if (strcmp(args[myidx], "expire") == 0) {
2863 myidx++;
2864 if (!*(args[myidx])) {
2865 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2866 file, linenum, args[myidx-1]);
2867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
2869 }
2870 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2871 if (err) {
2872 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2873 file, linenum, *err, args[myidx-1]);
2874 err_code |= ERR_ALERT | ERR_FATAL;
2875 goto out;
2876 }
2877 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002878 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002879 }
2880 else if (strcmp(args[myidx], "nopurge") == 0) {
2881 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002882 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002883 }
2884 else if (strcmp(args[myidx], "type") == 0) {
2885 myidx++;
2886 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2887 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2888 file, linenum, args[myidx]);
2889 err_code |= ERR_ALERT | ERR_FATAL;
2890 goto out;
2891 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002892 /* myidx already points to next arg */
2893 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002894 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002895 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002896 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002897
2898 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002899 nw = args[myidx];
2900 while (*nw) {
2901 /* the "store" keyword supports a comma-separated list */
2902 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002903 sa = NULL; /* store arg */
2904 while (*nw && *nw != ',') {
2905 if (*nw == '(') {
2906 *nw = 0;
2907 sa = ++nw;
2908 while (*nw != ')') {
2909 if (!*nw) {
2910 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2911 file, linenum, args[0], cw);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915 nw++;
2916 }
2917 *nw = '\0';
2918 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002919 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002920 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002921 if (*nw)
2922 *nw++ = '\0';
2923 type = stktable_get_data_type(cw);
2924 if (type < 0) {
2925 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2926 file, linenum, args[0], cw);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
Willy Tarreauac782882010-06-20 10:41:54 +02002930
2931 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2932 switch (err) {
2933 case PE_NONE: break;
2934 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002935 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2936 file, linenum, args[0], cw);
2937 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002938 break;
2939
2940 case PE_ARG_MISSING:
2941 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2942 file, linenum, args[0], cw);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945
2946 case PE_ARG_NOT_USED:
2947 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2948 file, linenum, args[0], cw);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951
2952 default:
2953 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2954 file, linenum, args[0], cw);
2955 err_code |= ERR_ALERT | ERR_FATAL;
2956 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002957 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002958 }
2959 myidx++;
2960 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002961 else {
2962 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2963 file, linenum, args[myidx]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002966 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002967 }
2968
2969 if (!curproxy->table.size) {
2970 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2971 file, linenum);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975
2976 if (curproxy->table.type == (unsigned int)-1) {
2977 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2978 file, linenum);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982 }
2983 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002984 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002985 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002986 int myidx = 0;
2987 const char *name = NULL;
2988 int flags;
2989
2990 if (curproxy == &defproxy) {
2991 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
2996 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2997 err_code |= ERR_WARN;
2998 goto out;
2999 }
3000
3001 myidx++;
3002 if ((strcmp(args[myidx], "store") == 0) ||
3003 (strcmp(args[myidx], "store-request") == 0)) {
3004 myidx++;
3005 flags = STK_IS_STORE;
3006 }
3007 else if (strcmp(args[myidx], "store-response") == 0) {
3008 myidx++;
3009 flags = STK_IS_STORE | STK_ON_RSP;
3010 }
3011 else if (strcmp(args[myidx], "match") == 0) {
3012 myidx++;
3013 flags = STK_IS_MATCH;
3014 }
3015 else if (strcmp(args[myidx], "on") == 0) {
3016 myidx++;
3017 flags = STK_IS_MATCH | STK_IS_STORE;
3018 }
3019 else {
3020 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
3025 if (*(args[myidx]) == 0) {
3026 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
3029 }
3030
David du Colombier7af46052012-05-16 14:16:48 +02003031 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003032 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003033 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
3036 }
3037
3038 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003039 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003040 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3041 file, linenum, args[0], expr->fetch->kw);
3042 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003043 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003044 goto out;
3045 }
3046 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003047 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003048 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3049 file, linenum, args[0], expr->fetch->kw);
3050 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003051 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003052 goto out;
3053 }
3054 }
3055
3056 if (strcmp(args[myidx], "table") == 0) {
3057 myidx++;
3058 name = args[myidx++];
3059 }
3060
Willy Tarreauef6494c2010-01-28 17:12:36 +01003061 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003062 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3063 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3064 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003065 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003066 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003067 goto out;
3068 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003069 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003070 else if (*(args[myidx])) {
3071 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3072 file, linenum, args[0], args[myidx]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003074 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003075 goto out;
3076 }
Emeric Brun97679e72010-09-23 17:56:44 +02003077 if (flags & STK_ON_RSP)
3078 err_code |= warnif_cond_requires_req(cond, file, linenum);
3079 else
3080 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003081
Emeric Brunb982a3d2010-01-04 15:45:53 +01003082 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3083 rule->cond = cond;
3084 rule->expr = expr;
3085 rule->flags = flags;
3086 rule->table.name = name ? strdup(name) : NULL;
3087 LIST_INIT(&rule->list);
3088 if (flags & STK_ON_RSP)
3089 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3090 else
3091 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3092 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003093 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003094 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003095 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003096
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3098 curproxy->uri_auth = NULL; /* we must detach from the default config */
3099
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003100 if (!*args[1]) {
3101 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003102 } else if (!strcmp(args[1], "admin")) {
3103 struct stats_admin_rule *rule;
3104
3105 if (curproxy == &defproxy) {
3106 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
3110
3111 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3112 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3113 err_code |= ERR_ALERT | ERR_ABORT;
3114 goto out;
3115 }
3116
3117 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3118 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3119 file, linenum, args[0], args[1]);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003123 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3124 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3125 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128 }
3129
3130 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3131
3132 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3133 rule->cond = cond;
3134 LIST_INIT(&rule->list);
3135 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003136 } else if (!strcmp(args[1], "uri")) {
3137 if (*(args[2]) == 0) {
3138 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003143 err_code |= ERR_ALERT | ERR_ABORT;
3144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
3146 } else if (!strcmp(args[1], "realm")) {
3147 if (*(args[2]) == 0) {
3148 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3152 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_ABORT;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003156 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003157 unsigned interval;
3158
3159 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3160 if (err) {
3161 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3162 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003165 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3166 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003167 err_code |= ERR_ALERT | ERR_ABORT;
3168 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003169 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003170 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003171 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003172
3173 if (curproxy == &defproxy) {
3174 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
3178
3179 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3180 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3181 err_code |= ERR_ALERT | ERR_ABORT;
3182 goto out;
3183 }
3184
Willy Tarreauff011f22011-01-06 17:51:27 +01003185 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3186 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003187 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3188 file, linenum, args[0]);
3189 err_code |= ERR_WARN;
3190 }
3191
Willy Tarreauff011f22011-01-06 17:51:27 +01003192 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003193
Willy Tarreauff011f22011-01-06 17:51:27 +01003194 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003195 err_code |= ERR_ALERT | ERR_ABORT;
3196 goto out;
3197 }
3198
Willy Tarreauff011f22011-01-06 17:51:27 +01003199 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3200 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003201
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 } else if (!strcmp(args[1], "auth")) {
3203 if (*(args[2]) == 0) {
3204 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003209 err_code |= ERR_ALERT | ERR_ABORT;
3210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 }
3212 } else if (!strcmp(args[1], "scope")) {
3213 if (*(args[2]) == 0) {
3214 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3218 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_ABORT;
3220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 }
3222 } else if (!strcmp(args[1], "enable")) {
3223 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3224 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_ABORT;
3226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003228 } else if (!strcmp(args[1], "hide-version")) {
3229 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3230 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003231 err_code |= ERR_ALERT | ERR_ABORT;
3232 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003233 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003234 } else if (!strcmp(args[1], "show-legends")) {
3235 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3236 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3237 err_code |= ERR_ALERT | ERR_ABORT;
3238 goto out;
3239 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003240 } else if (!strcmp(args[1], "show-node")) {
3241
3242 if (*args[2]) {
3243 int i;
3244 char c;
3245
3246 for (i=0; args[2][i]; i++) {
3247 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003248 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3249 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003250 break;
3251 }
3252
3253 if (!i || args[2][i]) {
3254 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3255 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3256 file, linenum, args[0], args[1]);
3257 err_code |= ERR_ALERT | ERR_FATAL;
3258 goto out;
3259 }
3260 }
3261
3262 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3263 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3264 err_code |= ERR_ALERT | ERR_ABORT;
3265 goto out;
3266 }
3267 } else if (!strcmp(args[1], "show-desc")) {
3268 char *desc = NULL;
3269
3270 if (*args[2]) {
3271 int i, len=0;
3272 char *d;
3273
3274 for(i=2; *args[i]; i++)
3275 len += strlen(args[i])+1;
3276
3277 desc = d = (char *)calloc(1, len);
3278
3279 d += sprintf(d, "%s", args[2]);
3280 for(i=3; *args[i]; i++)
3281 d += sprintf(d, " %s", args[i]);
3282 }
3283
3284 if (!*args[2] && !global.desc)
3285 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3286 file, linenum, args[1]);
3287 else {
3288 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3289 free(desc);
3290 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3291 err_code |= ERR_ALERT | ERR_ABORT;
3292 goto out;
3293 }
3294 free(desc);
3295 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003296 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003297stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003298 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 +01003299 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
3303 }
3304 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003305 int optnum;
3306
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003307 if (*(args[1]) == '\0') {
3308 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3309 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
3311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003313
3314 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3315 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003316 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3317 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3318 file, linenum, cfg_opts[optnum].name);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
Willy Tarreau93893792009-07-23 13:19:11 +02003322 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3323 err_code |= ERR_WARN;
3324 goto out;
3325 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003326
Willy Tarreau3842f002009-06-14 11:39:52 +02003327 curproxy->no_options &= ~cfg_opts[optnum].val;
3328 curproxy->options &= ~cfg_opts[optnum].val;
3329
3330 switch (kwm) {
3331 case KWM_STD:
3332 curproxy->options |= cfg_opts[optnum].val;
3333 break;
3334 case KWM_NO:
3335 curproxy->no_options |= cfg_opts[optnum].val;
3336 break;
3337 case KWM_DEF: /* already cleared */
3338 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003339 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003340
Willy Tarreau93893792009-07-23 13:19:11 +02003341 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003342 }
3343 }
3344
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003345 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3346 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003347 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3348 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3349 file, linenum, cfg_opts2[optnum].name);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352 }
Willy Tarreau93893792009-07-23 13:19:11 +02003353 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3354 err_code |= ERR_WARN;
3355 goto out;
3356 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003357
Willy Tarreau3842f002009-06-14 11:39:52 +02003358 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3359 curproxy->options2 &= ~cfg_opts2[optnum].val;
3360
3361 switch (kwm) {
3362 case KWM_STD:
3363 curproxy->options2 |= cfg_opts2[optnum].val;
3364 break;
3365 case KWM_NO:
3366 curproxy->no_options2 |= cfg_opts2[optnum].val;
3367 break;
3368 case KWM_DEF: /* already cleared */
3369 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003370 }
Willy Tarreau93893792009-07-23 13:19:11 +02003371 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003372 }
3373 }
3374
Willy Tarreau3842f002009-06-14 11:39:52 +02003375 if (kwm != KWM_STD) {
3376 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003377 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003380 }
3381
Emeric Brun3a058f32009-06-30 18:26:00 +02003382 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003383 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003385 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003386 if (*(args[2]) != '\0') {
3387 if (!strcmp(args[2], "clf")) {
3388 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003389 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003390 } else {
3391 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003392 err_code |= ERR_ALERT | ERR_FATAL;
3393 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003394 }
3395 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003396 if (curproxy->logformat_string != default_http_log_format &&
3397 curproxy->logformat_string != default_tcp_log_format &&
3398 curproxy->logformat_string != clf_http_log_format)
3399 free(curproxy->logformat_string);
3400 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003401 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003402 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003404 if (curproxy->logformat_string != default_http_log_format &&
3405 curproxy->logformat_string != default_tcp_log_format &&
3406 curproxy->logformat_string != clf_http_log_format)
3407 free(curproxy->logformat_string);
3408 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003409 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 else if (!strcmp(args[1], "tcpka")) {
3411 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003412 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003413 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003414
3415 if (curproxy->cap & PR_CAP_FE)
3416 curproxy->options |= PR_O_TCP_CLI_KA;
3417 if (curproxy->cap & PR_CAP_BE)
3418 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 }
3420 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003421 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_WARN;
3423
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003425 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003426 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003427 curproxy->options2 &= ~PR_O2_CHK_ANY;
3428 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 if (!*args[2]) { /* no argument */
3430 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3431 curproxy->check_len = strlen(DEF_CHECK_REQ);
3432 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003433 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 curproxy->check_req = (char *)malloc(reqlen);
3435 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003436 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003438 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439 if (*args[4])
3440 reqlen += strlen(args[4]);
3441 else
3442 reqlen += strlen("HTTP/1.0");
3443
3444 curproxy->check_req = (char *)malloc(reqlen);
3445 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003446 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003448 }
3449 else if (!strcmp(args[1], "ssl-hello-chk")) {
3450 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003451 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003452 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003453
Willy Tarreaua534fea2008-08-03 12:19:50 +02003454 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003455 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003456 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003457 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 }
Willy Tarreau23677902007-05-08 23:50:35 +02003459 else if (!strcmp(args[1], "smtpchk")) {
3460 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003461 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003462 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003463 curproxy->options2 &= ~PR_O2_CHK_ANY;
3464 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003465
3466 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3467 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3468 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3469 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3470 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3471 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3472 curproxy->check_req = (char *)malloc(reqlen);
3473 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3474 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3475 } else {
3476 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3477 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3478 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3479 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3480 }
3481 }
3482 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003483 else if (!strcmp(args[1], "pgsql-check")) {
3484 /* use PostgreSQL request to check servers' health */
3485 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3486 err_code |= ERR_WARN;
3487
3488 free(curproxy->check_req);
3489 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003490 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003491 curproxy->options2 |= PR_O2_PGSQL_CHK;
3492
3493 if (*(args[2])) {
3494 int cur_arg = 2;
3495
3496 while (*(args[cur_arg])) {
3497 if (strcmp(args[cur_arg], "user") == 0) {
3498 char * packet;
3499 uint32_t packet_len;
3500 uint32_t pv;
3501
3502 /* suboption header - needs additional argument for it */
3503 if (*(args[cur_arg+1]) == 0) {
3504 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3505 file, linenum, args[0], args[1], args[cur_arg]);
3506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
3508 }
3509
3510 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3511 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3512 pv = htonl(0x30000); /* protocol version 3.0 */
3513
3514 packet = (char*) calloc(1, packet_len);
3515
3516 memcpy(packet + 4, &pv, 4);
3517
3518 /* copy "user" */
3519 memcpy(packet + 8, "user", 4);
3520
3521 /* copy username */
3522 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3523
3524 free(curproxy->check_req);
3525 curproxy->check_req = packet;
3526 curproxy->check_len = packet_len;
3527
3528 packet_len = htonl(packet_len);
3529 memcpy(packet, &packet_len, 4);
3530 cur_arg += 2;
3531 } else {
3532 /* unknown suboption - catchall */
3533 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3534 file, linenum, args[0], args[1]);
3535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
3537 }
3538 } /* end while loop */
3539 }
3540 }
3541
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003542 else if (!strcmp(args[1], "redis-check")) {
3543 /* use REDIS PING request to check servers' health */
3544 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3545 err_code |= ERR_WARN;
3546
3547 free(curproxy->check_req);
3548 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003549 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003550 curproxy->options2 |= PR_O2_REDIS_CHK;
3551
3552 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3553 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3554 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3555 }
3556
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003557 else if (!strcmp(args[1], "mysql-check")) {
3558 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003559 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3560 err_code |= ERR_WARN;
3561
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003562 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003563 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003564 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003565 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003566
3567 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3568 * const char mysql40_client_auth_pkt[] = {
3569 * "\x0e\x00\x00" // packet length
3570 * "\x01" // packet number
3571 * "\x00\x00" // client capabilities
3572 * "\x00\x00\x01" // max packet
3573 * "haproxy\x00" // username (null terminated string)
3574 * "\x00" // filler (always 0x00)
3575 * "\x01\x00\x00" // packet length
3576 * "\x00" // packet number
3577 * "\x01" // COM_QUIT command
3578 * };
3579 */
3580
3581 if (*(args[2])) {
3582 int cur_arg = 2;
3583
3584 while (*(args[cur_arg])) {
3585 if (strcmp(args[cur_arg], "user") == 0) {
3586 char *mysqluser;
3587 int packetlen, reqlen, userlen;
3588
3589 /* suboption header - needs additional argument for it */
3590 if (*(args[cur_arg+1]) == 0) {
3591 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3592 file, linenum, args[0], args[1], args[cur_arg]);
3593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
3595 }
3596 mysqluser = args[cur_arg + 1];
3597 userlen = strlen(mysqluser);
3598 packetlen = userlen + 7;
3599 reqlen = packetlen + 9;
3600
3601 free(curproxy->check_req);
3602 curproxy->check_req = (char *)calloc(1, reqlen);
3603 curproxy->check_len = reqlen;
3604
3605 snprintf(curproxy->check_req, 4, "%c%c%c",
3606 ((unsigned char) packetlen & 0xff),
3607 ((unsigned char) (packetlen >> 8) & 0xff),
3608 ((unsigned char) (packetlen >> 16) & 0xff));
3609
3610 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003611 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003612 curproxy->check_req[8] = 1;
3613 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3614 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3615 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3616 cur_arg += 2;
3617 } else {
3618 /* unknown suboption - catchall */
3619 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3620 file, linenum, args[0], args[1]);
3621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
3623 }
3624 } /* end while loop */
3625 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003626 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003627 else if (!strcmp(args[1], "ldap-check")) {
3628 /* use LDAP request to check servers' health */
3629 free(curproxy->check_req);
3630 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003631 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003632 curproxy->options2 |= PR_O2_LDAP_CHK;
3633
3634 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3635 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3636 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3637 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003638 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003639 int cur_arg;
3640
3641 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3642 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003643 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003644
Willy Tarreau87cf5142011-08-19 22:57:24 +02003645 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003646
3647 free(curproxy->fwdfor_hdr_name);
3648 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3649 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3650
3651 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3652 cur_arg = 2;
3653 while (*(args[cur_arg])) {
3654 if (!strcmp(args[cur_arg], "except")) {
3655 /* suboption except - needs additional argument for it */
3656 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3657 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3658 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003661 }
3662 /* flush useless bits */
3663 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003664 cur_arg += 2;
3665 } else if (!strcmp(args[cur_arg], "header")) {
3666 /* suboption header - needs additional argument for it */
3667 if (*(args[cur_arg+1]) == 0) {
3668 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3669 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_ALERT | ERR_FATAL;
3671 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003672 }
3673 free(curproxy->fwdfor_hdr_name);
3674 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3675 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3676 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003677 } else if (!strcmp(args[cur_arg], "if-none")) {
3678 curproxy->options &= ~PR_O_FF_ALWAYS;
3679 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003680 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003681 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003682 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003683 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003686 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003687 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003688 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003689 else if (!strcmp(args[1], "originalto")) {
3690 int cur_arg;
3691
3692 /* insert x-original-to field, but not for the IP address listed as an except.
3693 * set default options (ie: bitfield, header name, etc)
3694 */
3695
3696 curproxy->options |= PR_O_ORGTO;
3697
3698 free(curproxy->orgto_hdr_name);
3699 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3700 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3701
Willy Tarreau87cf5142011-08-19 22:57:24 +02003702 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003703 cur_arg = 2;
3704 while (*(args[cur_arg])) {
3705 if (!strcmp(args[cur_arg], "except")) {
3706 /* suboption except - needs additional argument for it */
3707 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3708 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3709 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003712 }
3713 /* flush useless bits */
3714 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3715 cur_arg += 2;
3716 } else if (!strcmp(args[cur_arg], "header")) {
3717 /* suboption header - needs additional argument for it */
3718 if (*(args[cur_arg+1]) == 0) {
3719 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3720 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003723 }
3724 free(curproxy->orgto_hdr_name);
3725 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3726 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3727 cur_arg += 2;
3728 } else {
3729 /* unknown suboption - catchall */
3730 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3731 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003734 }
3735 } /* end while loop */
3736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 else {
3738 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003741 }
Willy Tarreau93893792009-07-23 13:19:11 +02003742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003744 else if (!strcmp(args[0], "default_backend")) {
3745 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003746 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003747
3748 if (*(args[1]) == 0) {
3749 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003752 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003753 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003754 curproxy->defbe.name = strdup(args[1]);
3755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003756 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003757 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003758 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003759
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003760 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003762 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763 /* enable reconnections to dispatch */
3764 curproxy->options |= PR_O_REDISP;
3765 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003766 else if (!strcmp(args[0], "http-check")) {
3767 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003769
3770 if (strcmp(args[1], "disable-on-404") == 0) {
3771 /* enable a graceful server shutdown on an HTTP 404 response */
3772 curproxy->options |= PR_O_DISABLE404;
3773 }
Willy Tarreauef781042010-01-27 11:53:01 +01003774 else if (strcmp(args[1], "send-state") == 0) {
3775 /* enable emission of the apparent state of a server in HTTP checks */
3776 curproxy->options2 |= PR_O2_CHK_SNDST;
3777 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003778 else if (strcmp(args[1], "expect") == 0) {
3779 const char *ptr_arg;
3780 int cur_arg;
3781
3782 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3783 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
3786 }
3787
3788 cur_arg = 2;
3789 /* consider exclamation marks, sole or at the beginning of a word */
3790 while (*(ptr_arg = args[cur_arg])) {
3791 while (*ptr_arg == '!') {
3792 curproxy->options2 ^= PR_O2_EXP_INV;
3793 ptr_arg++;
3794 }
3795 if (*ptr_arg)
3796 break;
3797 cur_arg++;
3798 }
3799 /* now ptr_arg points to the beginning of a word past any possible
3800 * exclamation mark, and cur_arg is the argument which holds this word.
3801 */
3802 if (strcmp(ptr_arg, "status") == 0) {
3803 if (!*(args[cur_arg + 1])) {
3804 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3805 file, linenum, args[0], args[1], ptr_arg);
3806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
3808 }
3809 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003810 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003811 curproxy->expect_str = strdup(args[cur_arg + 1]);
3812 }
3813 else if (strcmp(ptr_arg, "string") == 0) {
3814 if (!*(args[cur_arg + 1])) {
3815 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3816 file, linenum, args[0], args[1], ptr_arg);
3817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
3819 }
3820 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003821 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003822 curproxy->expect_str = strdup(args[cur_arg + 1]);
3823 }
3824 else if (strcmp(ptr_arg, "rstatus") == 0) {
3825 if (!*(args[cur_arg + 1])) {
3826 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3827 file, linenum, args[0], args[1], ptr_arg);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003832 free(curproxy->expect_str);
3833 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3834 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003835 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3836 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3837 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3838 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842 }
3843 else if (strcmp(ptr_arg, "rstring") == 0) {
3844 if (!*(args[cur_arg + 1])) {
3845 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3846 file, linenum, args[0], args[1], ptr_arg);
3847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
3849 }
3850 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003851 free(curproxy->expect_str);
3852 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3853 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003854 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3855 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3856 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3857 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861 }
3862 else {
3863 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3864 file, linenum, args[0], args[1], ptr_arg);
3865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
3867 }
3868 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003869 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003870 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 +02003871 err_code |= ERR_ALERT | ERR_FATAL;
3872 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003873 }
3874 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003875 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003876 if (curproxy == &defproxy) {
3877 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003880 }
3881
Willy Tarreaub80c2302007-11-30 20:51:32 +01003882 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003884
3885 if (strcmp(args[1], "fail") == 0) {
3886 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003887 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003888 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3889 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003892 }
3893
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003894 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3895 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3896 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003899 }
3900 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3901 }
3902 else {
3903 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003904 err_code |= ERR_ALERT | ERR_FATAL;
3905 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003906 }
3907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003908#ifdef TPROXY
3909 else if (!strcmp(args[0], "transparent")) {
3910 /* enable transparent proxy connections */
3911 curproxy->options |= PR_O_TRANSP;
3912 }
3913#endif
3914 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003915 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003916 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003917
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918 if (*(args[1]) == 0) {
3919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\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 }
3923 curproxy->maxconn = atol(args[1]);
3924 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003925 else if (!strcmp(args[0], "backlog")) { /* backlog */
3926 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003928
3929 if (*(args[1]) == 0) {
3930 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003931 err_code |= ERR_ALERT | ERR_FATAL;
3932 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003933 }
3934 curproxy->backlog = atol(args[1]);
3935 }
Willy Tarreau86034312006-12-29 00:10:33 +01003936 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003937 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003939
Willy Tarreau86034312006-12-29 00:10:33 +01003940 if (*(args[1]) == 0) {
3941 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003944 }
3945 curproxy->fullconn = atol(args[1]);
3946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003947 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3948 if (*(args[1]) == 0) {
3949 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003952 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003953 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3954 if (err) {
3955 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3956 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003959 }
3960 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003961 }
3962 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003963 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 if (curproxy == &defproxy) {
3965 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003969 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003971
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 if (strchr(args[1], ':') == NULL) {
3973 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003977 sk = str2sa(args[1]);
3978 if (!sk) {
3979 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
3982 }
3983 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003984 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003985 }
3986 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003987 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003989
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003990 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3991 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003992 err_code |= ERR_ALERT | ERR_FATAL;
3993 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003996 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3997 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3998 err_code |= ERR_WARN;
3999
4000 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4001 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4002 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4003 }
4004 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4005 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4006 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4007 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004008 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4009 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4010 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4011 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004012 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004013 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
4016 }
4017 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004018 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004019 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004020 char *rport, *raddr;
4021 short realport = 0;
4022 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004023
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004024 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004029 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031
4032 if (!*args[2]) {
4033 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4034 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004037 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004038
4039 err = invalid_char(args[1]);
4040 if (err) {
4041 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4042 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004045 }
4046
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004047 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004048 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004049
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004050 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4051 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4052 err_code |= ERR_ALERT | ERR_ABORT;
4053 goto out;
4054 }
4055
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004056 /* the servers are linked backwards first */
4057 newsrv->next = curproxy->srv;
4058 curproxy->srv = newsrv;
4059 newsrv->proxy = curproxy;
4060 newsrv->conf.file = file;
4061 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004062
Simon Hormanaf514952011-06-21 14:34:57 +09004063 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004064 LIST_INIT(&newsrv->pendconns);
4065 do_check = 0;
4066 newsrv->state = SRV_RUNNING; /* early server setup */
4067 newsrv->last_change = now.tv_sec;
4068 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004069
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004070 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004071 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004072 * - IP: => port=+0, relative
4073 * - IP:N => port=N, absolute
4074 * - IP:+N => port=+N, relative
4075 * - IP:-N => port=-N, relative
4076 */
4077 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004078 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004079 if (rport) {
4080 *rport++ = 0;
4081 realport = atol(rport);
4082 if (!isdigit((unsigned char)*rport))
4083 newsrv->state |= SRV_MAPPORTS;
4084 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004085 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004086
Willy Tarreaufab5a432011-03-04 15:31:53 +01004087 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004088 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004089 if (!sk) {
4090 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4091 err_code |= ERR_ALERT | ERR_FATAL;
4092 goto out;
4093 }
4094 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004095 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreaud02394b2012-05-11 18:32:18 +02004096 newsrv->sock = &sock_raw;
4097 newsrv->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004098
4099 if (!sk) {
4100 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4101 file, linenum, newsrv->addr.ss_family, args[2]);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
4104 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004105 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004106
4107 newsrv->check_port = curproxy->defsrv.check_port;
4108 newsrv->inter = curproxy->defsrv.inter;
4109 newsrv->fastinter = curproxy->defsrv.fastinter;
4110 newsrv->downinter = curproxy->defsrv.downinter;
4111 newsrv->rise = curproxy->defsrv.rise;
4112 newsrv->fall = curproxy->defsrv.fall;
4113 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4114 newsrv->minconn = curproxy->defsrv.minconn;
4115 newsrv->maxconn = curproxy->defsrv.maxconn;
4116 newsrv->slowstart = curproxy->defsrv.slowstart;
4117 newsrv->onerror = curproxy->defsrv.onerror;
4118 newsrv->consecutive_errors_limit
4119 = curproxy->defsrv.consecutive_errors_limit;
4120 newsrv->uweight = newsrv->iweight
4121 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004123 newsrv->curfd = -1; /* no health-check in progress */
4124 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004125
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004126 cur_arg = 3;
4127 } else {
4128 newsrv = &curproxy->defsrv;
4129 cur_arg = 1;
4130 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004131
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004133 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004134 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004135
4136 if (!*args[cur_arg + 1]) {
4137 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4138 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004141 }
4142
4143 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004144 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004145
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004146 if (newsrv->puid <= 0) {
4147 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004148 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004151 }
4152
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004153 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4154 if (node) {
4155 struct server *target = container_of(node, struct server, conf.id);
4156 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4157 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4158 err_code |= ERR_ALERT | ERR_FATAL;
4159 goto out;
4160 }
4161 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004162 cur_arg += 2;
4163 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004164 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 newsrv->cookie = strdup(args[cur_arg + 1]);
4166 newsrv->cklen = strlen(args[cur_arg + 1]);
4167 cur_arg += 2;
4168 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004169 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004170 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4171 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4172 cur_arg += 2;
4173 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004175 if (!*args[cur_arg + 1]) {
4176 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4177 file, linenum, args[cur_arg]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004183 if (newsrv->rise <= 0) {
4184 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4185 file, linenum, args[cur_arg]);
4186 err_code |= ERR_ALERT | ERR_FATAL;
4187 goto out;
4188 }
4189
Willy Tarreau96839092010-03-29 10:02:24 +02004190 if (newsrv->health)
4191 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004192 cur_arg += 2;
4193 }
4194 else if (!strcmp(args[cur_arg], "fall")) {
4195 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004196
4197 if (!*args[cur_arg + 1]) {
4198 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4199 file, linenum, args[cur_arg]);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
4203
4204 if (newsrv->fall <= 0) {
4205 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4206 file, linenum, args[cur_arg]);
4207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
4209 }
4210
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 cur_arg += 2;
4212 }
4213 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004214 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4215 if (err) {
4216 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4217 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004220 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004221 if (val <= 0) {
4222 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4223 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004224 err_code |= ERR_ALERT | ERR_FATAL;
4225 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004226 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004227 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 cur_arg += 2;
4229 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004230 else if (!strcmp(args[cur_arg], "fastinter")) {
4231 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4232 if (err) {
4233 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4234 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004237 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004238 if (val <= 0) {
4239 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4240 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004243 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004244 newsrv->fastinter = val;
4245 cur_arg += 2;
4246 }
4247 else if (!strcmp(args[cur_arg], "downinter")) {
4248 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4249 if (err) {
4250 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4251 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004254 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004255 if (val <= 0) {
4256 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4257 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004260 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004261 newsrv->downinter = val;
4262 cur_arg += 2;
4263 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004264 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004265 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004266 if (!sk) {
4267 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4268 err_code |= ERR_ALERT | ERR_FATAL;
4269 goto out;
4270 }
4271 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004272 cur_arg += 2;
4273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 else if (!strcmp(args[cur_arg], "port")) {
4275 newsrv->check_port = atol(args[cur_arg + 1]);
4276 cur_arg += 2;
4277 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004278 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004279 newsrv->state |= SRV_BACKUP;
4280 cur_arg ++;
4281 }
Simon Hormanfa461682011-06-25 09:39:49 +09004282 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4283 newsrv->state |= SRV_NON_STICK;
4284 cur_arg ++;
4285 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004286 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4287 newsrv->state |= SRV_SEND_PROXY;
4288 cur_arg ++;
4289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 else if (!strcmp(args[cur_arg], "weight")) {
4291 int w;
4292 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004293 if (w < 0 || w > 256) {
4294 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004295 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004298 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004299 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 cur_arg += 2;
4301 }
4302 else if (!strcmp(args[cur_arg], "minconn")) {
4303 newsrv->minconn = atol(args[cur_arg + 1]);
4304 cur_arg += 2;
4305 }
4306 else if (!strcmp(args[cur_arg], "maxconn")) {
4307 newsrv->maxconn = atol(args[cur_arg + 1]);
4308 cur_arg += 2;
4309 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004310 else if (!strcmp(args[cur_arg], "maxqueue")) {
4311 newsrv->maxqueue = atol(args[cur_arg + 1]);
4312 cur_arg += 2;
4313 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004314 else if (!strcmp(args[cur_arg], "slowstart")) {
4315 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004316 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004317 if (err) {
4318 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4319 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004322 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004323 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004324 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4325 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004326 err_code |= ERR_ALERT | ERR_FATAL;
4327 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004328 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004329 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004330 cur_arg += 2;
4331 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004332 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004333
4334 if (!*args[cur_arg + 1]) {
4335 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4336 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004339 }
4340
4341 newsrv->trackit = strdup(args[cur_arg + 1]);
4342
4343 cur_arg += 2;
4344 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004345 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 global.maxsock++;
4347 do_check = 1;
4348 cur_arg += 1;
4349 }
Willy Tarreau96839092010-03-29 10:02:24 +02004350 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4351 newsrv->state |= SRV_MAINTAIN;
4352 newsrv->state &= ~SRV_RUNNING;
4353 newsrv->health = 0;
4354 cur_arg += 1;
4355 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004356 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004357 if (!strcmp(args[cur_arg + 1], "none"))
4358 newsrv->observe = HANA_OBS_NONE;
4359 else if (!strcmp(args[cur_arg + 1], "layer4"))
4360 newsrv->observe = HANA_OBS_LAYER4;
4361 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4362 if (curproxy->mode != PR_MODE_HTTP) {
4363 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4364 file, linenum, args[cur_arg + 1]);
4365 err_code |= ERR_ALERT;
4366 }
4367 newsrv->observe = HANA_OBS_LAYER7;
4368 }
4369 else {
4370 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004371 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004372 file, linenum, args[cur_arg], args[cur_arg + 1]);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376
4377 cur_arg += 2;
4378 }
4379 else if (!strcmp(args[cur_arg], "on-error")) {
4380 if (!strcmp(args[cur_arg + 1], "fastinter"))
4381 newsrv->onerror = HANA_ONERR_FASTINTER;
4382 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4383 newsrv->onerror = HANA_ONERR_FAILCHK;
4384 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4385 newsrv->onerror = HANA_ONERR_SUDDTH;
4386 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4387 newsrv->onerror = HANA_ONERR_MARKDWN;
4388 else {
4389 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004390 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004391 file, linenum, args[cur_arg], args[cur_arg + 1]);
4392 err_code |= ERR_ALERT | ERR_FATAL;
4393 goto out;
4394 }
4395
4396 cur_arg += 2;
4397 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004398 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4399 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4400 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4401 else {
4402 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4403 file, linenum, args[cur_arg], args[cur_arg + 1]);
4404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
4406 }
4407
4408 cur_arg += 2;
4409 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004410 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4411 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4412 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4413 else {
4414 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4415 file, linenum, args[cur_arg], args[cur_arg + 1]);
4416 err_code |= ERR_ALERT | ERR_FATAL;
4417 goto out;
4418 }
4419
4420 cur_arg += 2;
4421 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004422 else if (!strcmp(args[cur_arg], "error-limit")) {
4423 if (!*args[cur_arg + 1]) {
4424 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4425 file, linenum, args[cur_arg]);
4426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
4428 }
4429
4430 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4431
4432 if (newsrv->consecutive_errors_limit <= 0) {
4433 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4434 file, linenum, args[cur_arg]);
4435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
4437 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004438 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004439 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004440 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004441 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004442 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004443
Willy Tarreaubaaee002006-06-26 02:48:02 +02004444 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004445#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004446 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004447 file, linenum, "source", "usesrc");
4448#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004449 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004451#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 }
4455 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004456 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4457 if (!sk) {
4458 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
4461 }
4462 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004463
4464 if (port_low != port_high) {
4465 int i;
4466 if (port_low <= 0 || port_low > 65535 ||
4467 port_high <= 0 || port_high > 65535 ||
4468 port_low > port_high) {
4469 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4470 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004473 }
4474 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4475 for (i = 0; i < newsrv->sport_range->size; i++)
4476 newsrv->sport_range->ports[i] = port_low + i;
4477 }
4478
Willy Tarreaubaaee002006-06-26 02:48:02 +02004479 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004480 while (*(args[cur_arg])) {
4481 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004482#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4483#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004484 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4485 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4486 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004489 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004490#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004491 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004492 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +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 }
4497 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004498 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004499 newsrv->state |= SRV_TPROXY_CLI;
4500 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004501 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004502 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004503 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4504 char *name, *end;
4505
4506 name = args[cur_arg+1] + 7;
4507 while (isspace(*name))
4508 name++;
4509
4510 end = name;
4511 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4512 end++;
4513
4514 newsrv->state &= ~SRV_TPROXY_MASK;
4515 newsrv->state |= SRV_TPROXY_DYN;
4516 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4517 newsrv->bind_hdr_len = end - name;
4518 memcpy(newsrv->bind_hdr_name, name, end - name);
4519 newsrv->bind_hdr_name[end-name] = '\0';
4520 newsrv->bind_hdr_occ = -1;
4521
4522 /* now look for an occurrence number */
4523 while (isspace(*end))
4524 end++;
4525 if (*end == ',') {
4526 end++;
4527 name = end;
4528 if (*end == '-')
4529 end++;
4530 while (isdigit(*end))
4531 end++;
4532 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4533 }
4534
4535 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4536 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4537 " occurrences values smaller than %d.\n",
4538 file, linenum, MAX_HDR_HISTORY);
4539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
4541 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004542 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004543 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004544 if (!sk) {
4545 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
4548 }
4549 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004550 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004551 }
4552 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004553#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004554 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004555#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004556 cur_arg += 2;
4557 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004558#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004559 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004560 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004561 err_code |= ERR_ALERT | ERR_FATAL;
4562 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004563#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4564 } /* "usesrc" */
4565
4566 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4567#ifdef SO_BINDTODEVICE
4568 if (!*args[cur_arg + 1]) {
4569 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004573 }
4574 if (newsrv->iface_name)
4575 free(newsrv->iface_name);
4576
4577 newsrv->iface_name = strdup(args[cur_arg + 1]);
4578 newsrv->iface_len = strlen(newsrv->iface_name);
4579 global.last_checks |= LSTCHK_NETADM;
4580#else
4581 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4582 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_ALERT | ERR_FATAL;
4584 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004585#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004586 cur_arg += 2;
4587 continue;
4588 }
4589 /* this keyword in not an option of "source" */
4590 break;
4591 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004593 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004594 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4595 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004599 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004600 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004601 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 +01004602 file, linenum, newsrv->id);
4603 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004604 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 +01004605 file, linenum);
4606
Willy Tarreau93893792009-07-23 13:19:11 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 }
4610 }
4611
4612 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004613 if (newsrv->trackit) {
4614 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4615 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004618 }
4619
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004620 /* try to get the port from check_addr if check_port not set */
4621 if (!newsrv->check_port)
4622 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004623
Willy Tarreaubaaee002006-06-26 02:48:02 +02004624 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4625 newsrv->check_port = realport; /* by default */
4626 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004627 /* not yet valid, because no port was set on
4628 * the server either. We'll check if we have
4629 * a known port on the first listener.
4630 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004631 struct listener *l = curproxy->listen;
4632 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4633 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004634 }
4635 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004636 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4637 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004640 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004641
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004642 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004643 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004644 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4645 err_code |= ERR_ALERT | ERR_ABORT;
4646 goto out;
4647 }
4648
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004649 /* Allocate buffer for partial check results... */
4650 if ((newsrv->check_conn = calloc(1, sizeof(struct connection))) == NULL) {
4651 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4652 err_code |= ERR_ALERT | ERR_ABORT;
4653 goto out;
4654 }
4655
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004656 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004657 newsrv->state |= SRV_CHECKED;
4658 }
4659
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004660 if (!defsrv) {
4661 if (newsrv->state & SRV_BACKUP)
4662 curproxy->srv_bck++;
4663 else
4664 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004665
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004666 newsrv->prev_state = newsrv->state;
4667 }
William Lallemanda73203e2012-03-12 12:48:57 +01004668 }
4669
4670 else if (strcmp(args[0], "unique-id-format") == 0) {
4671 if (!*(args[1])) {
4672 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4673 err_code |= ERR_ALERT | ERR_FATAL;
4674 goto out;
4675 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004676 free(curproxy->uniqueid_format_string);
4677 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004678 }
William Lallemanda73203e2012-03-12 12:48:57 +01004679
4680 else if (strcmp(args[0], "unique-id-header") == 0) {
4681 if (!*(args[1])) {
4682 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
4686 free(curproxy->header_unique_id);
4687 curproxy->header_unique_id = strdup(args[1]);
4688 }
4689
William Lallemand723b73a2012-02-08 16:37:49 +01004690 else if (strcmp(args[0], "log-format") == 0) {
4691 if (!*(args[1])) {
4692 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4693 err_code |= ERR_ALERT | ERR_FATAL;
4694 goto out;
4695 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004696
4697 if (curproxy->logformat_string != default_http_log_format &&
4698 curproxy->logformat_string != default_tcp_log_format &&
4699 curproxy->logformat_string != clf_http_log_format)
4700 free(curproxy->logformat_string);
4701 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 }
William Lallemand723b73a2012-02-08 16:37:49 +01004703
William Lallemand0f99e342011-10-12 17:50:54 +02004704 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4705 /* delete previous herited or defined syslog servers */
4706 struct logsrv *back;
4707
4708 if (*(args[1]) != 0) {
4709 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
4712 }
4713
William Lallemand723b73a2012-02-08 16:37:49 +01004714 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4715 LIST_DEL(&tmplogsrv->list);
4716 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004717 }
4718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004719 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004720 struct logsrv *logsrv;
4721
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004723 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004724 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004725 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004726 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004727 LIST_INIT(&node->list);
4728 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4729 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004730 }
4731 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004732
4733 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734
William Lallemand0f99e342011-10-12 17:50:54 +02004735 logsrv->facility = get_log_facility(args[2]);
4736 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
4740
Willy Tarreaubaaee002006-06-26 02:48:02 +02004741 }
4742
William Lallemand0f99e342011-10-12 17:50:54 +02004743 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004745 logsrv->level = get_log_level(args[3]);
4746 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
4750
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 }
4752 }
4753
William Lallemand0f99e342011-10-12 17:50:54 +02004754 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004755 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004756 logsrv->minlvl = get_log_level(args[4]);
4757 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004758 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004762 }
4763 }
4764
Robert Tsai81ae1952007-12-05 10:47:29 +01004765 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004766 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004767 if (!sk) {
4768 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004769 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
William Lallemand0f99e342011-10-12 17:50:54 +02004773 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004774 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004775 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004776 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004777 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
William Lallemand0f99e342011-10-12 17:50:54 +02004781 logsrv->addr = *sk;
4782 if (!get_host_port(&logsrv->addr))
4783 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004784 }
William Lallemand0f99e342011-10-12 17:50:54 +02004785
4786 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004787 }
4788 else {
4789 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4790 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
4794 }
4795 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004796 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004797 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004798
Willy Tarreau977b8e42006-12-29 14:19:17 +01004799 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004800 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004801
Willy Tarreaubaaee002006-06-26 02:48:02 +02004802 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004803 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4804 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004807 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004808
4809 /* we must first clear any optional default setting */
4810 curproxy->options &= ~PR_O_TPXY_MASK;
4811 free(curproxy->iface_name);
4812 curproxy->iface_name = NULL;
4813 curproxy->iface_len = 0;
4814
Willy Tarreaud5191e72010-02-09 20:50:45 +01004815 sk = str2sa(args[1]);
4816 if (!sk) {
4817 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
4820 }
4821 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004823
4824 cur_arg = 2;
4825 while (*(args[cur_arg])) {
4826 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004827#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4828#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004829 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4830 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4831 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004832 err_code |= ERR_ALERT | ERR_FATAL;
4833 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004834 }
4835#endif
4836 if (!*args[cur_arg + 1]) {
4837 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4838 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004841 }
4842
4843 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004844 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004845 curproxy->options |= PR_O_TPXY_CLI;
4846 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004847 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004848 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004849 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4850 char *name, *end;
4851
4852 name = args[cur_arg+1] + 7;
4853 while (isspace(*name))
4854 name++;
4855
4856 end = name;
4857 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4858 end++;
4859
4860 curproxy->options &= ~PR_O_TPXY_MASK;
4861 curproxy->options |= PR_O_TPXY_DYN;
4862 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4863 curproxy->bind_hdr_len = end - name;
4864 memcpy(curproxy->bind_hdr_name, name, end - name);
4865 curproxy->bind_hdr_name[end-name] = '\0';
4866 curproxy->bind_hdr_occ = -1;
4867
4868 /* now look for an occurrence number */
4869 while (isspace(*end))
4870 end++;
4871 if (*end == ',') {
4872 end++;
4873 name = end;
4874 if (*end == '-')
4875 end++;
4876 while (isdigit(*end))
4877 end++;
4878 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4879 }
4880
4881 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4882 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4883 " occurrences values smaller than %d.\n",
4884 file, linenum, MAX_HDR_HISTORY);
4885 err_code |= ERR_ALERT | ERR_FATAL;
4886 goto out;
4887 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004888 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004889 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004890 if (!sk) {
4891 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4892 err_code |= ERR_ALERT | ERR_FATAL;
4893 goto out;
4894 }
4895 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004896 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004897 }
4898 global.last_checks |= LSTCHK_NETADM;
4899#if !defined(CONFIG_HAP_LINUX_TPROXY)
4900 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004901#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004902#else /* no TPROXY support */
4903 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004904 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004907#endif
4908 cur_arg += 2;
4909 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004910 }
4911
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004912 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4913#ifdef SO_BINDTODEVICE
4914 if (!*args[cur_arg + 1]) {
4915 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004919 }
4920 if (curproxy->iface_name)
4921 free(curproxy->iface_name);
4922
4923 curproxy->iface_name = strdup(args[cur_arg + 1]);
4924 curproxy->iface_len = strlen(curproxy->iface_name);
4925 global.last_checks |= LSTCHK_NETADM;
4926#else
4927 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4928 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004931#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004932 cur_arg += 2;
4933 continue;
4934 }
4935 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4936 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004939 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004941 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4942 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4943 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004948 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4950 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004951 err_code |= ERR_ALERT | ERR_FATAL;
4952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954
4955 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004956 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004957 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004958 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
4961 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004962 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004963 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004964 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004965 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004967 }
4968 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004969 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004970 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004971 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004972 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004976 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004977 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004978 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004979 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004981 }
4982 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004983 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004984 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004985 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004986 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004989 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004990 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004991 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004992 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004993 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004994 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004995 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004996 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004997 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004998 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004999 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005000 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005001 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005002 }
5003 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005004 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005005 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005006 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005007 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005008 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005009 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005011 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005012 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5013 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005016 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005017
5018 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005019 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005020 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005021 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005022 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005023 }
5024 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005025 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005026 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005027 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005028 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
5031 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005032 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005033 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005034 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005035 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
5038 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005039 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005040 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005041 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005042 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 }
5045 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005046 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005047 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005048 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005049 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005050 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005051 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005052 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005053 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005054 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005055 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005057 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005058 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005059 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005060 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005061
Willy Tarreaubaaee002006-06-26 02:48:02 +02005062 if (curproxy == &defproxy) {
5063 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005066 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005067 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005068 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005069
Willy Tarreaubaaee002006-06-26 02:48:02 +02005070 if (*(args[1]) == 0) {
5071 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005074 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005075
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005076 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005077 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5078 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5079 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
5082 }
5083 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5084 }
5085 else if (*args[2]) {
5086 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5087 file, linenum, args[0], args[2]);
5088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
5090 }
5091
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005092 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005093 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005094 wl->s = strdup(args[1]);
5095 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005096 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005097 }
5098 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005099 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005100 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5101 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005104 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005105
Willy Tarreauade5ec42010-01-28 19:33:49 +01005106 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005107 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005108 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005109 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005111 }
5112 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005113 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005114 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005115 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005116 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005117 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 }
5119 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005120 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005121 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005122 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005123 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005125 }
5126 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005127 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005128 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5129 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005132 }
5133
Willy Tarreauade5ec42010-01-28 19:33:49 +01005134 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005135 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005136 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005137 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005139 }
5140 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005141 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005142 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005143 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005144 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005146 }
5147 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005149 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005150 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005151 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 }
5154 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005155 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005156
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 if (curproxy == &defproxy) {
5158 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005162 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005163 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 if (*(args[1]) == 0) {
5166 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 }
5170
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005171 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005172 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5173 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5174 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
5177 }
5178 err_code |= warnif_cond_requires_req(cond, file, linenum);
5179 }
5180 else if (*args[2]) {
5181 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5182 file, linenum, args[0], args[2]);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
5186
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005187 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005188 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005189 wl->s = strdup(args[1]);
5190 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
5192 else if (!strcmp(args[0], "errorloc") ||
5193 !strcmp(args[0], "errorloc302") ||
5194 !strcmp(args[0], "errorloc303")) { /* error location */
5195 int errnum, errlen;
5196 char *err;
5197
Willy Tarreau977b8e42006-12-29 14:19:17 +01005198 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005200
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005202 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 }
5206
5207 errnum = atol(args[1]);
5208 if (!strcmp(args[0], "errorloc303")) {
5209 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5210 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5211 } else {
5212 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5213 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5214 }
5215
Willy Tarreau0f772532006-12-23 20:51:41 +01005216 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5217 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005218 chunk_destroy(&curproxy->errmsg[rc]);
5219 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005220 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005223
5224 if (rc >= HTTP_ERR_SIZE) {
5225 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5226 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 free(err);
5228 }
5229 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005230 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5231 int errnum, errlen, fd;
5232 char *err;
5233 struct stat stat;
5234
5235 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005236 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005237
5238 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005239 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005242 }
5243
5244 fd = open(args[2], O_RDONLY);
5245 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5246 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5247 file, linenum, args[2], args[1]);
5248 if (fd >= 0)
5249 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005252 }
5253
Willy Tarreau27a674e2009-08-17 07:23:33 +02005254 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005255 errlen = stat.st_size;
5256 } else {
5257 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005258 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005259 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005260 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005261 }
5262
5263 err = malloc(errlen); /* malloc() must succeed during parsing */
5264 errnum = read(fd, err, errlen);
5265 if (errnum != errlen) {
5266 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5267 file, linenum, args[2], args[1]);
5268 close(fd);
5269 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005272 }
5273 close(fd);
5274
5275 errnum = atol(args[1]);
5276 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5277 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005278 chunk_destroy(&curproxy->errmsg[rc]);
5279 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005280 break;
5281 }
5282 }
5283
5284 if (rc >= HTTP_ERR_SIZE) {
5285 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5286 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005288 free(err);
5289 }
5290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005292 struct cfg_kw_list *kwl;
5293 int index;
5294
5295 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5296 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5297 if (kwl->kw[index].section != CFG_LISTEN)
5298 continue;
5299 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5300 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02005301 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005302 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005303 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005304 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005305 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005308 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005309 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005310 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005311 err_code |= ERR_WARN;
5312 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005313 }
Willy Tarreau93893792009-07-23 13:19:11 +02005314 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005315 }
5316 }
5317 }
5318
Willy Tarreau6daf3432008-01-22 16:44:08 +01005319 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005322 }
Willy Tarreau93893792009-07-23 13:19:11 +02005323 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005324 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005325 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326}
5327
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005328int
5329cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5330{
5331
5332 int err_code = 0;
5333 const char *err;
5334
5335 if (!strcmp(args[0], "userlist")) { /* new userlist */
5336 struct userlist *newul;
5337
5338 if (!*args[1]) {
5339 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5340 file, linenum, args[0]);
5341 err_code |= ERR_ALERT | ERR_FATAL;
5342 goto out;
5343 }
5344
5345 err = invalid_char(args[1]);
5346 if (err) {
5347 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5348 file, linenum, *err, args[0], args[1]);
5349 err_code |= ERR_ALERT | ERR_FATAL;
5350 goto out;
5351 }
5352
5353 for (newul = userlist; newul; newul = newul->next)
5354 if (!strcmp(newul->name, args[1])) {
5355 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5356 file, linenum, args[1]);
5357 err_code |= ERR_WARN;
5358 goto out;
5359 }
5360
5361 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5362 if (!newul) {
5363 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5364 err_code |= ERR_ALERT | ERR_ABORT;
5365 goto out;
5366 }
5367
5368 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5369 newul->name = strdup(args[1]);
5370
5371 if (!newul->groupusers | !newul->name) {
5372 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5373 err_code |= ERR_ALERT | ERR_ABORT;
5374 goto out;
5375 }
5376
5377 newul->next = userlist;
5378 userlist = newul;
5379
5380 } else if (!strcmp(args[0], "group")) { /* new group */
5381 int cur_arg, i;
5382 const char *err;
5383
5384 if (!*args[1]) {
5385 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5386 file, linenum, args[0]);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 }
5390
5391 err = invalid_char(args[1]);
5392 if (err) {
5393 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5394 file, linenum, *err, args[0], args[1]);
5395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
5397 }
5398
5399 for(i = 0; i < userlist->grpcnt; i++)
5400 if (!strcmp(userlist->groups[i], args[1])) {
5401 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5402 file, linenum, args[1], userlist->name);
5403 err_code |= ERR_ALERT;
5404 goto out;
5405 }
5406
5407 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5408 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5409 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5410 err_code |= ERR_ALERT | ERR_FATAL;
5411 goto out;
5412 }
5413
5414 cur_arg = 2;
5415
5416 while (*args[cur_arg]) {
5417 if (!strcmp(args[cur_arg], "users")) {
5418 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5419 cur_arg += 2;
5420 continue;
5421 } else {
5422 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5423 file, linenum, args[0]);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
5427 }
5428
5429 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5430 } else if (!strcmp(args[0], "user")) { /* new user */
5431 struct auth_users *newuser;
5432 int cur_arg;
5433
5434 if (!*args[1]) {
5435 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5436 file, linenum, args[0]);
5437 err_code |= ERR_ALERT | ERR_FATAL;
5438 goto out;
5439 }
5440
5441 for (newuser = userlist->users; newuser; newuser = newuser->next)
5442 if (!strcmp(newuser->user, args[1])) {
5443 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5444 file, linenum, args[1], userlist->name);
5445 err_code |= ERR_ALERT;
5446 goto out;
5447 }
5448
5449 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5450 if (!newuser) {
5451 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5452 err_code |= ERR_ALERT | ERR_ABORT;
5453 goto out;
5454 }
5455
5456 newuser->user = strdup(args[1]);
5457
5458 newuser->next = userlist->users;
5459 userlist->users = newuser;
5460
5461 cur_arg = 2;
5462
5463 while (*args[cur_arg]) {
5464 if (!strcmp(args[cur_arg], "password")) {
5465#ifndef CONFIG_HAP_CRYPT
5466 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5467 file, linenum);
5468 err_code |= ERR_ALERT;
5469#endif
5470 newuser->pass = strdup(args[cur_arg + 1]);
5471 cur_arg += 2;
5472 continue;
5473 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5474 newuser->pass = strdup(args[cur_arg + 1]);
5475 newuser->flags |= AU_O_INSECURE;
5476 cur_arg += 2;
5477 continue;
5478 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005479 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005480 cur_arg += 2;
5481 continue;
5482 } else {
5483 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5484 file, linenum, args[0]);
5485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
5487 }
5488 }
5489 } else {
5490 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5491 err_code |= ERR_ALERT | ERR_FATAL;
5492 }
5493
5494out:
5495 return err_code;
5496}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497
5498/*
5499 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005500 * Returns the error code, 0 if OK, or any combination of :
5501 * - ERR_ABORT: must abort ASAP
5502 * - ERR_FATAL: we can continue parsing but not start the service
5503 * - ERR_WARN: a warning has been emitted
5504 * - ERR_ALERT: an alert has been emitted
5505 * Only the two first ones can stop processing, the two others are just
5506 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005508int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005510 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511 FILE *f;
5512 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005513 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005514 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005515
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 if ((f=fopen(file,"r")) == NULL)
5517 return -1;
5518
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005519 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005520 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005521 char *end;
5522 char *args[MAX_LINE_ARGS + 1];
5523 char *line = thisline;
5524
Willy Tarreaubaaee002006-06-26 02:48:02 +02005525 linenum++;
5526
5527 end = line + strlen(line);
5528
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005529 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5530 /* Check if we reached the limit and the last char is not \n.
5531 * Watch out for the last line without the terminating '\n'!
5532 */
5533 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005534 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005536 }
5537
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005539 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 line++;
5541
5542 arg = 0;
5543 args[arg] = line;
5544
5545 while (*line && arg < MAX_LINE_ARGS) {
5546 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5547 * C equivalent value. Other combinations left unchanged (eg: \1).
5548 */
5549 if (*line == '\\') {
5550 int skip = 0;
5551 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5552 *line = line[1];
5553 skip = 1;
5554 }
5555 else if (line[1] == 'r') {
5556 *line = '\r';
5557 skip = 1;
5558 }
5559 else if (line[1] == 'n') {
5560 *line = '\n';
5561 skip = 1;
5562 }
5563 else if (line[1] == 't') {
5564 *line = '\t';
5565 skip = 1;
5566 }
5567 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005568 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 unsigned char hex1, hex2;
5570 hex1 = toupper(line[2]) - '0';
5571 hex2 = toupper(line[3]) - '0';
5572 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5573 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5574 *line = (hex1<<4) + hex2;
5575 skip = 3;
5576 }
5577 else {
5578 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005579 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 }
5581 }
5582 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005583 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 end -= skip;
5585 }
5586 line++;
5587 }
5588 else if (*line == '#' || *line == '\n' || *line == '\r') {
5589 /* end of string, end of loop */
5590 *line = 0;
5591 break;
5592 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005593 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005595 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005596 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597 line++;
5598 args[++arg] = line;
5599 }
5600 else {
5601 line++;
5602 }
5603 }
5604
5605 /* empty line */
5606 if (!**args)
5607 continue;
5608
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005609 if (*line) {
5610 /* we had to stop due to too many args.
5611 * Let's terminate the string, print the offending part then cut the
5612 * last arg.
5613 */
5614 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5615 line++;
5616 *line = '\0';
5617
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005618 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005619 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005620 err_code |= ERR_ALERT | ERR_FATAL;
5621 args[arg] = line;
5622 }
5623
Willy Tarreau540abe42007-05-02 20:50:16 +02005624 /* zero out remaining args and ensure that at least one entry
5625 * is zeroed out.
5626 */
5627 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 args[arg] = line;
5629 }
5630
Willy Tarreau3842f002009-06-14 11:39:52 +02005631 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005632 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005633 char *tmp;
5634
Willy Tarreau3842f002009-06-14 11:39:52 +02005635 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005636 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005637 for (arg=0; *args[arg+1]; arg++)
5638 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005639 *tmp = '\0'; // fix the next arg to \0
5640 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005641 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005642 else if (!strcmp(args[0], "default")) {
5643 kwm = KWM_DEF;
5644 for (arg=0; *args[arg+1]; arg++)
5645 args[arg] = args[arg+1]; // shift args after inversion
5646 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005647
William Lallemand0f99e342011-10-12 17:50:54 +02005648 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5649 strcmp(args[0], "log") != 0) {
5650 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005651 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005652 }
5653
Willy Tarreau977b8e42006-12-29 14:19:17 +01005654 if (!strcmp(args[0], "listen") ||
5655 !strcmp(args[0], "frontend") ||
5656 !strcmp(args[0], "backend") ||
5657 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005658 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005660 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005661 cursection = strdup(args[0]);
5662 }
5663 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005664 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005665 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005666 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005667 }
5668 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005669 confsect = CFG_USERLIST;
5670 free(cursection);
5671 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005672 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005673 else if (!strcmp(args[0], "peers")) {
5674 confsect = CFG_PEERS;
5675 free(cursection);
5676 cursection = strdup(args[0]);
5677 }
5678
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 /* else it's a section keyword */
5680
5681 switch (confsect) {
5682 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005683 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 break;
5685 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005686 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005688 case CFG_USERLIST:
5689 err_code |= cfg_parse_users(file, linenum, args, kwm);
5690 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005691 case CFG_PEERS:
5692 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5693 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005695 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005696 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005697 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005698
5699 if (err_code & ERR_ABORT)
5700 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005702 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005703 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005704 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005705 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005706}
5707
Willy Tarreaubb925012009-07-23 13:36:36 +02005708/*
5709 * Returns the error code, 0 if OK, or any combination of :
5710 * - ERR_ABORT: must abort ASAP
5711 * - ERR_FATAL: we can continue parsing but not start the service
5712 * - ERR_WARN: a warning has been emitted
5713 * - ERR_ALERT: an alert has been emitted
5714 * Only the two first ones can stop processing, the two others are just
5715 * indicators.
5716 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005717int check_config_validity()
5718{
5719 int cfgerr = 0;
5720 struct proxy *curproxy = NULL;
5721 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005722 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005723 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005724 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725
5726 /*
5727 * Now, check for the integrity of all that we have collected.
5728 */
5729
5730 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005731 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005732
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005733 /* first, we will invert the proxy list order */
5734 curproxy = NULL;
5735 while (proxy) {
5736 struct proxy *next;
5737
5738 next = proxy->next;
5739 proxy->next = curproxy;
5740 curproxy = proxy;
5741 if (!next)
5742 break;
5743 proxy = next;
5744 }
5745
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005747 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005748 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005749 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005750 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005751 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005752 unsigned int next_id;
5753
5754 if (!curproxy->uuid) {
5755 /* proxy ID not set, use automatic numbering with first
5756 * spare entry starting with next_pxid.
5757 */
5758 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5759 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5760 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005761 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005762 next_pxid++;
5763
Willy Tarreau55ea7572007-06-17 19:56:27 +02005764
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005766 /* ensure we don't keep listeners uselessly bound */
5767 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 curproxy = curproxy->next;
5769 continue;
5770 }
5771
Willy Tarreauff01a212009-03-15 13:46:16 +01005772 switch (curproxy->mode) {
5773 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005774 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005775 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005776 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5777 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005778 cfgerr++;
5779 }
5780
5781 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005782 Warning("config : servers will be ignored for %s '%s'.\n",
5783 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005784 break;
5785
5786 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005787 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005788 break;
5789
5790 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005791 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005792 break;
5793 }
5794
5795 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005796 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5797 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 cfgerr++;
5799 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005800
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005801 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005802 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005803 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005804 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5805 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005806 cfgerr++;
5807 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005809 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005810 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5811 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005812 cfgerr++;
5813 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005815 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005816 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5817 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005818 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005819 }
5820 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005821 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005822 /* If no LB algo is set in a backend, and we're not in
5823 * transparent mode, dispatch mode nor proxy mode, we
5824 * want to use balance roundrobin by default.
5825 */
5826 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5827 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 }
5829 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005830
Willy Tarreau1620ec32011-08-06 17:05:02 +02005831 if (curproxy->options & PR_O_DISPATCH)
5832 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5833 else if (curproxy->options & PR_O_HTTP_PROXY)
5834 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5835 else if (curproxy->options & PR_O_TRANSP)
5836 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005837
Willy Tarreau1620ec32011-08-06 17:05:02 +02005838 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5839 if (curproxy->options & PR_O_DISABLE404) {
5840 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5841 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5842 err_code |= ERR_WARN;
5843 curproxy->options &= ~PR_O_DISABLE404;
5844 }
5845 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5846 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5847 "send-state", proxy_type_str(curproxy), curproxy->id);
5848 err_code |= ERR_WARN;
5849 curproxy->options &= ~PR_O2_CHK_SNDST;
5850 }
Willy Tarreauef781042010-01-27 11:53:01 +01005851 }
5852
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005853 /* if a default backend was specified, let's find it */
5854 if (curproxy->defbe.name) {
5855 struct proxy *target;
5856
Alex Williams96532db2009-11-01 21:27:13 -05005857 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005858 if (!target) {
5859 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5860 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005861 cfgerr++;
5862 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005863 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5864 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005865 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005866 } else {
5867 free(curproxy->defbe.name);
5868 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005869 /* we force the backend to be present on at least all of
5870 * the frontend's processes.
5871 */
5872 target->bind_proc = curproxy->bind_proc ?
5873 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005874
5875 /* Emit a warning if this proxy also has some servers */
5876 if (curproxy->srv) {
5877 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5878 curproxy->id);
5879 err_code |= ERR_WARN;
5880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 }
5882 }
5883
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005884 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005885 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5886 /* map jump target for ACT_SETBE in req_rep chain */
5887 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005888 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005889 struct proxy *target;
5890
Willy Tarreaua496b602006-12-17 23:15:24 +01005891 if (exp->action != ACT_SETBE)
5892 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005893
Alex Williams96532db2009-11-01 21:27:13 -05005894 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005895 if (!target) {
5896 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5897 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005898 cfgerr++;
5899 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005900 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5901 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005902 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005903 } else {
5904 free((void *)exp->replace);
5905 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005906 /* we force the backend to be present on at least all of
5907 * the frontend's processes.
5908 */
5909 target->bind_proc = curproxy->bind_proc ?
5910 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005911 }
5912 }
5913 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005914
5915 /* find the target proxy for 'use_backend' rules */
5916 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005917 struct proxy *target;
5918
Alex Williams96532db2009-11-01 21:27:13 -05005919 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005920
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005921 if (!target) {
5922 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5923 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005924 cfgerr++;
5925 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005926 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5927 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005928 cfgerr++;
5929 } else {
5930 free((void *)rule->be.name);
5931 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005932 /* we force the backend to be present on at least all of
5933 * the frontend's processes.
5934 */
5935 target->bind_proc = curproxy->bind_proc ?
5936 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005937 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005938 }
5939
5940 /* find the target proxy for 'use_backend' rules */
5941 list_for_each_entry(srule, &curproxy->server_rules, list) {
5942 struct server *target = findserver(curproxy, srule->srv.name);
5943
5944 if (!target) {
5945 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5946 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5947 cfgerr++;
5948 continue;
5949 }
5950 free((void *)srule->srv.name);
5951 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005952 }
5953
Emeric Brunb982a3d2010-01-04 15:45:53 +01005954 /* find the target table for 'stick' rules */
5955 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5956 struct proxy *target;
5957
Emeric Brun1d33b292010-01-04 15:47:17 +01005958 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5959 if (mrule->flags & STK_IS_STORE)
5960 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5961
Emeric Brunb982a3d2010-01-04 15:45:53 +01005962 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005963 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005964 else
5965 target = curproxy;
5966
5967 if (!target) {
5968 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5969 curproxy->id, mrule->table.name);
5970 cfgerr++;
5971 }
5972 else if (target->table.size == 0) {
5973 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5974 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5975 cfgerr++;
5976 }
Willy Tarreau12785782012-04-27 21:37:17 +02005977 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
5978 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01005979 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5980 cfgerr++;
5981 }
5982 else {
5983 free((void *)mrule->table.name);
5984 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005985 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005986 }
5987 }
5988
5989 /* find the target table for 'store response' rules */
5990 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5991 struct proxy *target;
5992
Emeric Brun1d33b292010-01-04 15:47:17 +01005993 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5994
Emeric Brunb982a3d2010-01-04 15:45:53 +01005995 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005996 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005997 else
5998 target = curproxy;
5999
6000 if (!target) {
6001 Alert("Proxy '%s': unable to find store table '%s'.\n",
6002 curproxy->id, mrule->table.name);
6003 cfgerr++;
6004 }
6005 else if (target->table.size == 0) {
6006 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6007 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6008 cfgerr++;
6009 }
Willy Tarreau12785782012-04-27 21:37:17 +02006010 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6011 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006012 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6013 cfgerr++;
6014 }
6015 else {
6016 free((void *)mrule->table.name);
6017 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006018 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006019 }
6020 }
6021
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006022 /* find the target table for 'tcp-request' layer 4 rules */
6023 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6024 struct proxy *target;
6025
Willy Tarreau56123282010-08-06 19:06:56 +02006026 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006027 continue;
6028
6029 if (trule->act_prm.trk_ctr.table.n)
6030 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6031 else
6032 target = curproxy;
6033
6034 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006035 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6036 curproxy->id, trule->act_prm.trk_ctr.table.n,
6037 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006038 cfgerr++;
6039 }
6040 else if (target->table.size == 0) {
6041 Alert("Proxy '%s': table '%s' used but not configured.\n",
6042 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6043 cfgerr++;
6044 }
6045 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006046 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 +02006047 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6048 cfgerr++;
6049 }
6050 else {
6051 free(trule->act_prm.trk_ctr.table.n);
6052 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006053 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006054 * to pass a list of counters to track and allocate them right here using
6055 * stktable_alloc_data_type().
6056 */
6057 }
6058 }
6059
Willy Tarreaud1f96522010-08-03 19:34:32 +02006060 /* find the target table for 'tcp-request' layer 6 rules */
6061 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6062 struct proxy *target;
6063
Willy Tarreau56123282010-08-06 19:06:56 +02006064 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006065 continue;
6066
6067 if (trule->act_prm.trk_ctr.table.n)
6068 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6069 else
6070 target = curproxy;
6071
6072 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006073 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6074 curproxy->id, trule->act_prm.trk_ctr.table.n,
6075 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006076 cfgerr++;
6077 }
6078 else if (target->table.size == 0) {
6079 Alert("Proxy '%s': table '%s' used but not configured.\n",
6080 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6081 cfgerr++;
6082 }
6083 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006084 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 +02006085 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6086 cfgerr++;
6087 }
6088 else {
6089 free(trule->act_prm.trk_ctr.table.n);
6090 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006091 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006092 * to pass a list of counters to track and allocate them right here using
6093 * stktable_alloc_data_type().
6094 */
6095 }
6096 }
6097
Emeric Brun32da3c42010-09-23 18:39:19 +02006098 if (curproxy->table.peers.name) {
6099 struct peers *curpeers = peers;
6100
6101 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6102 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6103 free((void *)curproxy->table.peers.name);
6104 curproxy->table.peers.p = peers;
6105 break;
6106 }
6107 }
6108
6109 if (!curpeers) {
6110 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6111 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006112 free((void *)curproxy->table.peers.name);
6113 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006114 cfgerr++;
6115 }
6116 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006117 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6118 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006119 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006120 cfgerr++;
6121 }
6122 }
6123
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006124 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006125 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006126 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6127 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6128 "proxy", curproxy->id);
6129 cfgerr++;
6130 goto out_uri_auth_compat;
6131 }
6132
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006133 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006134 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006135 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006136 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006137
Willy Tarreau95fa4692010-02-01 13:05:50 +01006138 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6139 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006140
6141 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006142 uri_auth_compat_req[i++] = "realm";
6143 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6144 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006145
Willy Tarreau95fa4692010-02-01 13:05:50 +01006146 uri_auth_compat_req[i++] = "unless";
6147 uri_auth_compat_req[i++] = "{";
6148 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6149 uri_auth_compat_req[i++] = "}";
6150 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006151
Willy Tarreauff011f22011-01-06 17:51:27 +01006152 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6153 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006154 cfgerr++;
6155 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006156 }
6157
Willy Tarreauff011f22011-01-06 17:51:27 +01006158 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006159
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006160 if (curproxy->uri_auth->auth_realm) {
6161 free(curproxy->uri_auth->auth_realm);
6162 curproxy->uri_auth->auth_realm = NULL;
6163 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006164
6165 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006166 }
6167out_uri_auth_compat:
6168
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006169 cfgerr += acl_find_targets(curproxy);
6170
Willy Tarreau2738a142006-07-08 17:28:09 +02006171 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006172 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006173 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006174 (!curproxy->timeout.connect ||
6175 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006176 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006177 " | While not properly invalid, you will certainly encounter various problems\n"
6178 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006179 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006180 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006181 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006182 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006183
Willy Tarreau1fa31262007-12-03 00:36:16 +01006184 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6185 * We must still support older configurations, so let's find out whether those
6186 * parameters have been set or must be copied from contimeouts.
6187 */
6188 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006189 if (!curproxy->timeout.tarpit ||
6190 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006191 /* tarpit timeout not set. We search in the following order:
6192 * default.tarpit, curr.connect, default.connect.
6193 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006194 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006195 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006196 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006197 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006198 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006199 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006200 }
6201 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006202 (!curproxy->timeout.queue ||
6203 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006204 /* queue timeout not set. We search in the following order:
6205 * default.queue, curr.connect, default.connect.
6206 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006207 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006208 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006209 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006210 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006211 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006212 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006213 }
6214 }
6215
Willy Tarreau1620ec32011-08-06 17:05:02 +02006216 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006217 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6218 curproxy->check_req = (char *)malloc(curproxy->check_len);
6219 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006220 }
6221
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006222 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006223 if (curproxy->nb_req_cap) {
6224 if (curproxy->mode == PR_MODE_HTTP) {
6225 curproxy->req_cap_pool = create_pool("ptrcap",
6226 curproxy->nb_req_cap * sizeof(char *),
6227 MEM_F_SHARED);
6228 } else {
6229 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6230 proxy_type_str(curproxy), curproxy->id);
6231 err_code |= ERR_WARN;
6232 curproxy->to_log &= ~LW_REQHDR;
6233 curproxy->nb_req_cap = 0;
6234 }
6235 }
6236
6237 if (curproxy->nb_rsp_cap) {
6238 if (curproxy->mode == PR_MODE_HTTP) {
6239 curproxy->rsp_cap_pool = create_pool("ptrcap",
6240 curproxy->nb_rsp_cap * sizeof(char *),
6241 MEM_F_SHARED);
6242 } else {
6243 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6244 proxy_type_str(curproxy), curproxy->id);
6245 err_code |= ERR_WARN;
6246 curproxy->to_log &= ~LW_REQHDR;
6247 curproxy->nb_rsp_cap = 0;
6248 }
6249 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006250
Willy Tarreau196729e2012-05-31 19:30:26 +02006251 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006252 if (!(curproxy->cap & PR_CAP_FE)) {
6253 if (curproxy->logformat_string != default_http_log_format &&
6254 curproxy->logformat_string != default_tcp_log_format &&
6255 curproxy->logformat_string != clf_http_log_format)
6256 free(curproxy->logformat_string);
6257 curproxy->logformat_string = NULL;
6258 }
6259
Willy Tarreau196729e2012-05-31 19:30:26 +02006260 if (curproxy->logformat_string)
6261 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6262
6263 if (curproxy->uniqueid_format_string)
6264 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6265
Willy Tarreaubaaee002006-06-26 02:48:02 +02006266 /* first, we will invert the servers list order */
6267 newsrv = NULL;
6268 while (curproxy->srv) {
6269 struct server *next;
6270
6271 next = curproxy->srv->next;
6272 curproxy->srv->next = newsrv;
6273 newsrv = curproxy->srv;
6274 if (!next)
6275 break;
6276 curproxy->srv = next;
6277 }
6278
Willy Tarreaudd701652010-05-25 23:03:02 +02006279 /* assign automatic UIDs to servers which don't have one yet */
6280 next_id = 1;
6281 newsrv = curproxy->srv;
6282 while (newsrv != NULL) {
6283 if (!newsrv->puid) {
6284 /* server ID not set, use automatic numbering with first
6285 * spare entry starting with next_svid.
6286 */
6287 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6288 newsrv->conf.id.key = newsrv->puid = next_id;
6289 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6290 }
6291 next_id++;
6292 newsrv = newsrv->next;
6293 }
6294
Willy Tarreau20697042007-11-15 23:26:18 +01006295 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006296 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297
Willy Tarreau62c3be22012-01-20 13:12:32 +01006298 /*
6299 * If this server supports a maxconn parameter, it needs a dedicated
6300 * tasks to fill the emptied slots when a connection leaves.
6301 * Also, resolve deferred tracking dependency if needed.
6302 */
6303 newsrv = curproxy->srv;
6304 while (newsrv != NULL) {
6305 if (newsrv->minconn > newsrv->maxconn) {
6306 /* Only 'minconn' was specified, or it was higher than or equal
6307 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6308 * this will avoid further useless expensive computations.
6309 */
6310 newsrv->maxconn = newsrv->minconn;
6311 } else if (newsrv->maxconn && !newsrv->minconn) {
6312 /* minconn was not specified, so we set it to maxconn */
6313 newsrv->minconn = newsrv->maxconn;
6314 }
6315
6316 if (newsrv->trackit) {
6317 struct proxy *px;
6318 struct server *srv;
6319 char *pname, *sname;
6320
6321 pname = newsrv->trackit;
6322 sname = strrchr(pname, '/');
6323
6324 if (sname)
6325 *sname++ = '\0';
6326 else {
6327 sname = pname;
6328 pname = NULL;
6329 }
6330
6331 if (pname) {
6332 px = findproxy(pname, PR_CAP_BE);
6333 if (!px) {
6334 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6335 proxy_type_str(curproxy), curproxy->id,
6336 newsrv->id, pname);
6337 cfgerr++;
6338 goto next_srv;
6339 }
6340 } else
6341 px = curproxy;
6342
6343 srv = findserver(px, sname);
6344 if (!srv) {
6345 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6346 proxy_type_str(curproxy), curproxy->id,
6347 newsrv->id, sname);
6348 cfgerr++;
6349 goto next_srv;
6350 }
6351
6352 if (!(srv->state & SRV_CHECKED)) {
6353 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6354 "tracking as it does not have checks enabled.\n",
6355 proxy_type_str(curproxy), curproxy->id,
6356 newsrv->id, px->id, srv->id);
6357 cfgerr++;
6358 goto next_srv;
6359 }
6360
6361 if (curproxy != px &&
6362 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6363 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6364 "tracking: disable-on-404 option inconsistency.\n",
6365 proxy_type_str(curproxy), curproxy->id,
6366 newsrv->id, px->id, srv->id);
6367 cfgerr++;
6368 goto next_srv;
6369 }
6370
6371 /* if the other server is forced disabled, we have to do the same here */
6372 if (srv->state & SRV_MAINTAIN) {
6373 newsrv->state |= SRV_MAINTAIN;
6374 newsrv->state &= ~SRV_RUNNING;
6375 newsrv->health = 0;
6376 }
6377
6378 newsrv->track = srv;
6379 newsrv->tracknext = srv->tracknext;
6380 srv->tracknext = newsrv;
6381
6382 free(newsrv->trackit);
6383 newsrv->trackit = NULL;
6384 }
6385 next_srv:
6386 newsrv = newsrv->next;
6387 }
6388
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006389 /* We have to initialize the server lookup mechanism depending
6390 * on what LB algorithm was choosen.
6391 */
6392
6393 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6394 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6395 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006396 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6397 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6398 init_server_map(curproxy);
6399 } else {
6400 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6401 fwrr_init_server_groups(curproxy);
6402 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006403 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006404
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006405 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006406 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6407 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6408 fwlc_init_server_tree(curproxy);
6409 } else {
6410 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6411 fas_init_server_tree(curproxy);
6412 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006413 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006414
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006415 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006416 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6417 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6418 chash_init_server_tree(curproxy);
6419 } else {
6420 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6421 init_server_map(curproxy);
6422 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006423 break;
6424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425
6426 if (curproxy->options & PR_O_LOGASAP)
6427 curproxy->to_log &= ~LW_BYTES;
6428
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006429 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006430 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006431 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6432 proxy_type_str(curproxy), curproxy->id);
6433 err_code |= ERR_WARN;
6434 }
6435
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006436 if (curproxy->mode != PR_MODE_HTTP) {
6437 int optnum;
6438
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006439 if (curproxy->uri_auth) {
6440 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6441 proxy_type_str(curproxy), curproxy->id);
6442 err_code |= ERR_WARN;
6443 curproxy->uri_auth = NULL;
6444 }
6445
Willy Tarreau87cf5142011-08-19 22:57:24 +02006446 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006447 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6448 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6449 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006450 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006451 }
6452
6453 if (curproxy->options & PR_O_ORGTO) {
6454 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6455 "originalto", proxy_type_str(curproxy), curproxy->id);
6456 err_code |= ERR_WARN;
6457 curproxy->options &= ~PR_O_ORGTO;
6458 }
6459
6460 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6461 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6462 (curproxy->cap & cfg_opts[optnum].cap) &&
6463 (curproxy->options & cfg_opts[optnum].val)) {
6464 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6465 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6466 err_code |= ERR_WARN;
6467 curproxy->options &= ~cfg_opts[optnum].val;
6468 }
6469 }
6470
6471 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6472 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6473 (curproxy->cap & cfg_opts2[optnum].cap) &&
6474 (curproxy->options2 & cfg_opts2[optnum].val)) {
6475 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6476 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6477 err_code |= ERR_WARN;
6478 curproxy->options2 &= ~cfg_opts2[optnum].val;
6479 }
6480 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006481
Willy Tarreauefa5f512010-03-30 20:13:29 +02006482#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006483 if (curproxy->bind_hdr_occ) {
6484 curproxy->bind_hdr_occ = 0;
6485 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6486 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6487 err_code |= ERR_WARN;
6488 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006489#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006490 }
6491
Willy Tarreaubaaee002006-06-26 02:48:02 +02006492 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006493 * ensure that we're not cross-dressing a TCP server into HTTP.
6494 */
6495 newsrv = curproxy->srv;
6496 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006497 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006498 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6499 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006500 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006501 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006502
Willy Tarreau0cec3312011-10-31 13:49:26 +01006503 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6504 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6505 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6506 err_code |= ERR_WARN;
6507 }
6508
Willy Tarreauefa5f512010-03-30 20:13:29 +02006509#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006510 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6511 newsrv->bind_hdr_occ = 0;
6512 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6513 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6514 err_code |= ERR_WARN;
6515 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006516#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006517 newsrv = newsrv->next;
6518 }
6519
Willy Tarreauc1a21672009-08-16 22:37:44 +02006520 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006521 curproxy->accept = frontend_accept;
6522
Willy Tarreauc1a21672009-08-16 22:37:44 +02006523 if (curproxy->tcp_req.inspect_delay ||
6524 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006525 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006526
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006527 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006528 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006529 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006530 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006531
6532 /* both TCP and HTTP must check switching rules */
6533 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6534 }
6535
6536 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006537 if (curproxy->tcp_req.inspect_delay ||
6538 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6539 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6540
Emeric Brun97679e72010-09-23 17:56:44 +02006541 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6542 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6543
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006544 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006545 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006546 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006547 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006548
6549 /* If the backend does requires RDP cookie persistence, we have to
6550 * enable the corresponding analyser.
6551 */
6552 if (curproxy->options2 & PR_O2_RDPC_PRST)
6553 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6554 }
6555
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006556 listener = NULL;
6557 while (curproxy->listen) {
6558 struct listener *next;
6559
6560 next = curproxy->listen->next;
6561 curproxy->listen->next = listener;
6562 listener = curproxy->listen;
6563
6564 if (!next)
6565 break;
6566
6567 curproxy->listen = next;
6568 }
6569
Willy Tarreaue6b98942007-10-29 01:09:36 +01006570 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006571 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006572 listener = curproxy->listen;
6573 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006574 if (!listener->luid) {
6575 /* listener ID not set, use automatic numbering with first
6576 * spare entry starting with next_luid.
6577 */
6578 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6579 listener->conf.id.key = listener->luid = next_id;
6580 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006581 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006582 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006583
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006584 /* enable separate counters */
6585 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6586 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6587 if (!listener->name) {
6588 sprintf(trash, "sock-%d", listener->luid);
6589 listener->name = strdup(trash);
6590 }
6591 }
6592
Willy Tarreaue6b98942007-10-29 01:09:36 +01006593 if (curproxy->options & PR_O_TCP_NOLING)
6594 listener->options |= LI_O_NOLINGER;
6595 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006596 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006597 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006598 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006599 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006600 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006601 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006602
Willy Tarreau8a956912010-10-15 14:27:08 +02006603 if (listener->options & LI_O_ACC_PROXY)
6604 listener->analysers |= AN_REQ_DECODE_PROXY;
6605
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006606 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6607 listener->options |= LI_O_TCP_RULES;
6608
Willy Tarreaude3041d2010-05-31 10:56:17 +02006609 if (curproxy->mon_mask.s_addr)
6610 listener->options |= LI_O_CHK_MONNET;
6611
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006612 /* smart accept mode is automatic in HTTP mode */
6613 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6614 (curproxy->mode == PR_MODE_HTTP &&
6615 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6616 listener->options |= LI_O_NOQUICKACK;
6617
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006618 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006619 listener = listener->next;
6620 }
6621
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006622 /* Check multi-process mode compatibility for the current proxy */
6623 if (global.nbproc > 1) {
6624 int nbproc = 0;
6625 if (curproxy->bind_proc) {
6626 int proc;
6627 for (proc = 0; proc < global.nbproc; proc++) {
6628 if (curproxy->bind_proc & (1 << proc)) {
6629 nbproc++;
6630 }
6631 }
6632 } else {
6633 nbproc = global.nbproc;
6634 }
6635 if (curproxy->table.peers.name) {
6636 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6637 curproxy->id);
6638 cfgerr++;
6639 }
6640 if (nbproc > 1) {
6641 if (curproxy->uri_auth) {
6642 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6643 curproxy->id);
6644 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6645 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6646 curproxy->id);
6647 }
6648 }
6649 if (curproxy->appsession_name) {
6650 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6651 curproxy->id);
6652 }
6653 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6654 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6655 curproxy->id);
6656 }
6657 }
6658 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006659
6660 /* create the task associated with the proxy */
6661 curproxy->task = task_new();
6662 if (curproxy->task) {
6663 curproxy->task->context = curproxy;
6664 curproxy->task->process = manage_proxy;
6665 /* no need to queue, it will be done automatically if some
6666 * listener gets limited.
6667 */
6668 curproxy->task->expire = TICK_ETERNITY;
6669 } else {
6670 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6671 curproxy->id);
6672 cfgerr++;
6673 }
6674
Willy Tarreaubaaee002006-06-26 02:48:02 +02006675 curproxy = curproxy->next;
6676 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006677
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006678 /* Check multi-process mode compatibility */
6679 if (global.nbproc > 1) {
6680 if (global.stats_fe) {
6681 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6682 }
6683 }
6684
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006685 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6686 struct auth_users *curuser;
6687 int g;
6688
6689 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6690 unsigned int group_mask = 0;
6691 char *group = NULL;
6692
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006693 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006694 continue;
6695
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006696 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006697
6698 for (g = 0; g < curuserlist->grpcnt; g++)
6699 if (!strcmp(curuserlist->groups[g], group))
6700 break;
6701
6702 if (g == curuserlist->grpcnt) {
6703 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6704 curuserlist->name, group, curuser->user);
6705 err_code |= ERR_ALERT | ERR_FATAL;
6706 goto out;
6707 }
6708
6709 group_mask |= (1 << g);
6710 }
6711
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006712 free(curuser->u.groups);
6713 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006714 }
6715
6716 for (g = 0; g < curuserlist->grpcnt; g++) {
6717 char *user = NULL;
6718
6719 if (!curuserlist->groupusers[g])
6720 continue;
6721
6722 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6723 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6724 if (!strcmp(curuser->user, user))
6725 break;
6726
6727 if (!curuser) {
6728 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6729 curuserlist->name, user, curuserlist->groups[g]);
6730 err_code |= ERR_ALERT | ERR_FATAL;
6731 goto out;
6732 }
6733
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006734 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006735 }
6736
6737 free(curuserlist->groupusers[g]);
6738 }
6739
6740 free(curuserlist->groupusers);
6741
6742#ifdef DEBUG_AUTH
6743 for (g = 0; g < curuserlist->grpcnt; g++) {
6744 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6745
6746 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006747 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006748 fprintf(stderr, " %s", curuser->user);
6749 }
6750
6751 fprintf(stderr, "\n");
6752 }
6753#endif
6754
Willy Tarreaufbb78422011-06-05 15:38:35 +02006755 }
6756
6757 /* automatically compute fullconn if not set. We must not do it in the
6758 * loop above because cross-references are not yet fully resolved.
6759 */
6760 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6761 /* If <fullconn> is not set, let's set it to 10% of the sum of
6762 * the possible incoming frontend's maxconns.
6763 */
6764 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6765 struct proxy *fe;
6766 int total = 0;
6767
6768 /* sum up the number of maxconns of frontends which
6769 * reference this backend at least once or which are
6770 * the same one ('listen').
6771 */
6772 for (fe = proxy; fe; fe = fe->next) {
6773 struct switching_rule *rule;
6774 struct hdr_exp *exp;
6775 int found = 0;
6776
6777 if (!(fe->cap & PR_CAP_FE))
6778 continue;
6779
6780 if (fe == curproxy) /* we're on a "listen" instance */
6781 found = 1;
6782
6783 if (fe->defbe.be == curproxy) /* "default_backend" */
6784 found = 1;
6785
6786 /* check if a "use_backend" rule matches */
6787 if (!found) {
6788 list_for_each_entry(rule, &fe->switching_rules, list) {
6789 if (rule->be.backend == curproxy) {
6790 found = 1;
6791 break;
6792 }
6793 }
6794 }
6795
6796 /* check if a "reqsetbe" rule matches */
6797 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6798 if (exp->action == ACT_SETBE &&
6799 (struct proxy *)exp->replace == curproxy) {
6800 found = 1;
6801 break;
6802 }
6803 }
6804
6805 /* now we've checked all possible ways to reference a backend
6806 * from a frontend.
6807 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006808 if (!found)
6809 continue;
6810 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006811 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006812 /* we have the sum of the maxconns in <total>. We only
6813 * keep 10% of that sum to set the default fullconn, with
6814 * a hard minimum of 1 (to avoid a divide by zero).
6815 */
6816 curproxy->fullconn = (total + 9) / 10;
6817 if (!curproxy->fullconn)
6818 curproxy->fullconn = 1;
6819 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006820 }
6821
Willy Tarreau056f5682010-06-06 15:51:11 +02006822 /* initialize stick-tables on backend capable proxies. This must not
6823 * be done earlier because the data size may be discovered while parsing
6824 * other proxies.
6825 */
6826 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006827 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006828
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006829 /*
6830 * Recount currently required checks.
6831 */
6832
6833 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6834 int optnum;
6835
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006836 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6837 if (curproxy->options & cfg_opts[optnum].val)
6838 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006839
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006840 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6841 if (curproxy->options2 & cfg_opts2[optnum].val)
6842 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006843 }
6844
Willy Tarreau122541c2011-09-07 21:24:49 +02006845 if (peers) {
6846 struct peers *curpeers = peers, **last;
6847 struct peer *p, *pb;
6848
6849 /* Remove all peers sections which don't have a valid listener.
6850 * This can happen when a peers section is never referenced and
6851 * does not contain a local peer.
6852 */
6853 last = &peers;
6854 while (*last) {
6855 curpeers = *last;
6856 if (curpeers->peers_fe) {
6857 last = &curpeers->next;
6858 continue;
6859 }
6860
6861 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6862 curpeers->id, localpeer);
6863
6864 p = curpeers->remote;
6865 while (p) {
6866 pb = p->next;
6867 free(p->id);
6868 free(p);
6869 p = pb;
6870 }
6871
6872 /* Destroy and unlink this curpeers section.
6873 * Note: curpeers is backed up into *last.
6874 */
6875 free(curpeers->id);
6876 curpeers = curpeers->next;
6877 free(*last);
6878 *last = curpeers;
6879 }
6880 }
6881
Willy Tarreauac1932d2011-10-24 19:14:41 +02006882 if (!global.tune.max_http_hdr)
6883 global.tune.max_http_hdr = MAX_HTTP_HDR;
6884
Willy Tarreau34eb6712011-10-24 18:15:04 +02006885 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006886 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006887 MEM_F_SHARED);
6888
Willy Tarreaubb925012009-07-23 13:36:36 +02006889 if (cfgerr > 0)
6890 err_code |= ERR_ALERT | ERR_FATAL;
6891 out:
6892 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006893}
6894
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006895/*
6896 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6897 * parsing sessions.
6898 */
6899void cfg_register_keywords(struct cfg_kw_list *kwl)
6900{
6901 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6902}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006903
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006904/*
6905 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6906 */
6907void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6908{
6909 LIST_DEL(&kwl->list);
6910 LIST_INIT(&kwl->list);
6911}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006912
6913/*
6914 * Local variables:
6915 * c-indent-level: 8
6916 * c-basic-offset: 8
6917 * End:
6918 */