blob: 978178345eea1b094764e713932cb896d0dc37e3 [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>
Willy Tarreauc7e42382012-08-24 19:22:53 +020029#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020031#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/memory.h>
33#include <common/standard.h>
34#include <common/time.h>
35#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
37#include <types/capture.h>
38#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020046#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020047#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020048#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020049#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010050#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020051#include <proto/lb_fwlc.h>
52#include <proto/lb_fwrr.h>
53#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020062#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020063#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010064#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020065#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010067#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068
69
Willy Tarreauf3c69202006-07-09 16:42:34 +020070/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
71 * ssl-hello-chk option to ensure that the remote server speaks SSL.
72 *
73 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
74 */
75const char sslv3_client_hello_pkt[] = {
76 "\x16" /* ContentType : 0x16 = Hanshake */
77 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
78 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
79 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
80 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
81 "\x03\x00" /* Hello Version : 0x0300 = v3 */
82 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
83 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
84 "\x00" /* Session ID length : empty (no session ID) */
85 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
86 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
87 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
88 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
89 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
90 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
91 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
92 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
93 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
94 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
95 "\x00\x38" "\x00\x39" "\x00\x3A"
96 "\x01" /* Compression Length : 0x01 = 1 byte for types */
97 "\x00" /* Compression Type : 0x00 = NULL compression */
98};
99
Willy Tarreau3842f002009-06-14 11:39:52 +0200100/* various keyword modifiers */
101enum kw_mod {
102 KWM_STD = 0, /* normal */
103 KWM_NO, /* "no" prefixed before the keyword */
104 KWM_DEF, /* "default" prefixed before the keyword */
105};
106
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100108struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100109 const char *name;
110 unsigned int val;
111 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100112 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100113 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100114};
115
116/* proxy->options */
117static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100118{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100119 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
120 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
121 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
122 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
123 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
124 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
125 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
127 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
129 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
130 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
131 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
132 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
133 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
134 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100135#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100136 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100137#else
138 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100139#endif
140
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100142};
143
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144/* proxy->options2 */
145static const struct cfg_opt cfg_opts2[] =
146{
147#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
149 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
150 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100151#else
152 { "splice-request", 0, 0, 0, 0 },
153 { "splice-response", 0, 0, 0, 0 },
154 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100155#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
157 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
158 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
159 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
160 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
161 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
162 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
163 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
164 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400165 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200167 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200168 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100169 { NULL, 0, 0, 0 }
170};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171
Willy Tarreau6daf3432008-01-22 16:44:08 +0100172static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
174int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100175int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200176
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200177/* List head of all known configuration keywords */
178static struct cfg_kw_list cfg_keywords = {
179 .list = LIST_HEAD_INIT(cfg_keywords.list)
180};
181
Willy Tarreaubaaee002006-06-26 02:48:02 +0200182/*
183 * converts <str> to a list of listeners which are dynamically allocated.
184 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
185 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
186 * - <port> is a numerical port from 1 to 65535 ;
187 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
188 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200189 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100191static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192{
193 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100194 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 int port, end;
196
197 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200198
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 while (next && *next) {
200 struct sockaddr_storage ss;
201
202 str = next;
203 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100204 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 *next++ = 0;
206 }
207
Emeric Bruned760922010-10-22 17:59:25 +0200208 if (*str == '/') {
209 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
210 /* so compute max path */
211 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
212 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 +0200213
Emeric Bruned760922010-10-22 17:59:25 +0200214 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100215 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
216 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200217 goto fail;
218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200221 ss.ss_family = AF_UNIX;
222 if (global.unix_bind.prefix) {
223 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
224 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225 }
Emeric Bruned760922010-10-22 17:59:25 +0200226 else {
227 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
228 }
229 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 }
231 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100232 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100234 ss2 = str2sa_range(str, &port, &end);
235 if (!ss2) {
236 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
237 file, line, str);
238 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100241 if (!port) {
242 Alert("parsing [%s:%d] : missing port number: '%s'\n",
243 file, line, str);
244 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100247 /* OK the address looks correct */
248 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Emeric Bruned760922010-10-22 17:59:25 +0200250 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100251 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
252 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200253 goto fail;
254 }
255
256 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100257 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
258 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 }
262
263 for (; port <= end; port++) {
264 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200265 l->next = curproxy->listen;
266 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267
268 l->fd = -1;
269 l->addr = ss;
Willy Tarreauc5788912012-08-24 18:12:41 +0200270 l->data = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100271 l->state = LI_INIT;
272
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100273 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100275 tcpv4_add_listener(l);
276 }
Emeric Bruned760922010-10-22 17:59:25 +0200277 else if (ss.ss_family == AF_INET6) {
278 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
279 tcpv6_add_listener(l);
280 }
281 else {
282 l->perm.ux.gid = l->perm.ux.uid = -1;
283 l->perm.ux.mode = 0;
284 uxst_add_listener(l);
285 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200286
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200287 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100288 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 } /* end for(port) */
290 } /* end while(next) */
291 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200292 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293 fail:
294 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200295 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296}
297
Willy Tarreau977b8e42006-12-29 14:19:17 +0100298/*
299 * Sends a warning if proxy <proxy> does not have at least one of the
300 * capabilities in <cap>. An optionnal <hint> may be added at the end
301 * of the warning to help the user. Returns 1 if a warning was emitted
302 * or 0 if the condition is valid.
303 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100304int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100305{
306 char *msg;
307
308 switch (cap) {
309 case PR_CAP_BE: msg = "no backend"; break;
310 case PR_CAP_FE: msg = "no frontend"; break;
311 case PR_CAP_RS: msg = "no ruleset"; break;
312 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
313 default: msg = "not enough"; break;
314 }
315
316 if (!(proxy->cap & cap)) {
317 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100318 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100319 return 1;
320 }
321 return 0;
322}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323
Willy Tarreau61d18892009-03-31 10:49:21 +0200324/* Report a warning if a rule is placed after a 'block' rule.
325 * Return 1 if the warning has been emitted, otherwise 0.
326 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100327int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200328{
329 if (!LIST_ISEMPTY(&proxy->block_cond)) {
330 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
331 file, line, arg);
332 return 1;
333 }
334 return 0;
335}
336
337/* Report a warning if a rule is placed after a reqrewrite rule.
338 * Return 1 if the warning has been emitted, otherwise 0.
339 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100340int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200341{
342 if (proxy->req_exp) {
343 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
344 file, line, arg);
345 return 1;
346 }
347 return 0;
348}
349
350/* Report a warning if a rule is placed after a reqadd rule.
351 * Return 1 if the warning has been emitted, otherwise 0.
352 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100353int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200354{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100355 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200356 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
357 file, line, arg);
358 return 1;
359 }
360 return 0;
361}
362
363/* Report a warning if a rule is placed after a redirect rule.
364 * Return 1 if the warning has been emitted, otherwise 0.
365 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100366int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200367{
368 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
369 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
370 file, line, arg);
371 return 1;
372 }
373 return 0;
374}
375
376/* Report a warning if a rule is placed after a 'use_backend' rule.
377 * Return 1 if the warning has been emitted, otherwise 0.
378 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100379int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200380{
381 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
382 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
383 file, line, arg);
384 return 1;
385 }
386 return 0;
387}
388
389/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
392 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
393 warnif_rule_after_reqadd(proxy, file, line, arg) ||
394 warnif_rule_after_redirect(proxy, file, line, arg) ||
395 warnif_rule_after_use_backend(proxy, file, line, arg);
396}
397
398/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100399int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200400{
401 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
402 warnif_rule_after_redirect(proxy, file, line, arg) ||
403 warnif_rule_after_use_backend(proxy, file, line, arg);
404}
405
406/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100407int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200408{
409 return warnif_rule_after_redirect(proxy, file, line, arg) ||
410 warnif_rule_after_use_backend(proxy, file, line, arg);
411}
412
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100413/* Report it if a request ACL condition uses some response-only parameters. It
414 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
415 * Note that <cond> may be NULL and then will be ignored.
416 */
417static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
418{
419 struct acl *acl;
420
421 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
422 return 0;
423
424 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
425 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
426 file, line, acl ? acl->name : "(unknown)");
427 return ERR_WARN;
428}
429
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100430/* Report it if a request ACL condition uses some request-only volatile parameters.
431 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
432 * Note that <cond> may be NULL and then will be ignored.
433 */
434static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
435{
436 struct acl *acl;
437
438 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
439 return 0;
440
441 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
442 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
443 file, line, acl ? acl->name : "(unknown)");
444 return ERR_WARN;
445}
446
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100447
Willy Tarreaubaaee002006-06-26 02:48:02 +0200448/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200449 * parse a line in a <global> section. Returns the error code, 0 if OK, or
450 * any combination of :
451 * - ERR_ABORT: must abort ASAP
452 * - ERR_FATAL: we can continue parsing but not start the service
453 * - ERR_WARN: a warning has been emitted
454 * - ERR_ALERT: an alert has been emitted
455 * Only the two first ones can stop processing, the two others are just
456 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200458int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200459{
Willy Tarreau058e9072009-07-20 09:30:05 +0200460 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200461 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462
463 if (!strcmp(args[0], "global")) { /* new section */
464 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200466 }
467 else if (!strcmp(args[0], "daemon")) {
468 global.mode |= MODE_DAEMON;
469 }
470 else if (!strcmp(args[0], "debug")) {
471 global.mode |= MODE_DEBUG;
472 }
473 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100474 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200476 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100477 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200478 }
479 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100480 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200482 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100483 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200484 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100485 else if (!strcmp(args[0], "nosplice")) {
486 global.tune.options &= ~GTUNE_USE_SPLICE;
487 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488 else if (!strcmp(args[0], "quiet")) {
489 global.mode |= MODE_QUIET;
490 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200491 else if (!strcmp(args[0], "tune.maxpollevents")) {
492 if (global.tune.maxpollevents != 0) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT;
495 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200501 }
502 global.tune.maxpollevents = atol(args[1]);
503 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100504 else if (!strcmp(args[0], "tune.maxaccept")) {
505 if (global.tune.maxaccept != 0) {
506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT;
508 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100509 }
510 if (*(args[1]) == 0) {
511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100514 }
515 global.tune.maxaccept = atol(args[1]);
516 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200517 else if (!strcmp(args[0], "tune.chksize")) {
518 if (*(args[1]) == 0) {
519 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
520 err_code |= ERR_ALERT | ERR_FATAL;
521 goto out;
522 }
523 global.tune.chksize = atol(args[1]);
524 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200525 else if (!strcmp(args[0], "tune.bufsize")) {
526 if (*(args[1]) == 0) {
527 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
528 err_code |= ERR_ALERT | ERR_FATAL;
529 goto out;
530 }
531 global.tune.bufsize = atol(args[1]);
532 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
533 global.tune.maxrewrite = global.tune.bufsize / 2;
David du Colombier7af46052012-05-16 14:16:48 +0200534 trashlen = global.tune.bufsize;
535 trash = realloc(trash, trashlen);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200536 }
537 else if (!strcmp(args[0], "tune.maxrewrite")) {
538 if (*(args[1]) == 0) {
539 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
540 err_code |= ERR_ALERT | ERR_FATAL;
541 goto out;
542 }
543 global.tune.maxrewrite = atol(args[1]);
544 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
545 global.tune.maxrewrite = global.tune.bufsize / 2;
546 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100547 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
548 if (global.tune.client_rcvbuf != 0) {
549 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
550 err_code |= ERR_ALERT;
551 goto out;
552 }
553 if (*(args[1]) == 0) {
554 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
555 err_code |= ERR_ALERT | ERR_FATAL;
556 goto out;
557 }
558 global.tune.client_rcvbuf = atol(args[1]);
559 }
560 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
561 if (global.tune.server_rcvbuf != 0) {
562 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
563 err_code |= ERR_ALERT;
564 goto out;
565 }
566 if (*(args[1]) == 0) {
567 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
568 err_code |= ERR_ALERT | ERR_FATAL;
569 goto out;
570 }
571 global.tune.server_rcvbuf = atol(args[1]);
572 }
573 else if (!strcmp(args[0], "tune.sndbuf.client")) {
574 if (global.tune.client_sndbuf != 0) {
575 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT;
577 goto out;
578 }
579 if (*(args[1]) == 0) {
580 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
581 err_code |= ERR_ALERT | ERR_FATAL;
582 goto out;
583 }
584 global.tune.client_sndbuf = atol(args[1]);
585 }
586 else if (!strcmp(args[0], "tune.sndbuf.server")) {
587 if (global.tune.server_sndbuf != 0) {
588 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
589 err_code |= ERR_ALERT;
590 goto out;
591 }
592 if (*(args[1]) == 0) {
593 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
594 err_code |= ERR_ALERT | ERR_FATAL;
595 goto out;
596 }
597 global.tune.server_sndbuf = atol(args[1]);
598 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200599 else if (!strcmp(args[0], "tune.pipesize")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.pipesize = atol(args[1]);
606 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200607 else if (!strcmp(args[0], "tune.http.maxhdr")) {
608 if (*(args[1]) == 0) {
609 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
610 err_code |= ERR_ALERT | ERR_FATAL;
611 goto out;
612 }
613 global.tune.max_http_hdr = atol(args[1]);
614 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 else if (!strcmp(args[0], "uid")) {
616 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200617 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200618 err_code |= ERR_ALERT;
619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200620 }
621 if (*(args[1]) == 0) {
622 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200623 err_code |= ERR_ALERT | ERR_FATAL;
624 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 }
626 global.uid = atol(args[1]);
627 }
628 else if (!strcmp(args[0], "gid")) {
629 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200630 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200631 err_code |= ERR_ALERT;
632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200633 }
634 if (*(args[1]) == 0) {
635 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200636 err_code |= ERR_ALERT | ERR_FATAL;
637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 }
639 global.gid = atol(args[1]);
640 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 /* user/group name handling */
642 else if (!strcmp(args[0], "user")) {
643 struct passwd *ha_user;
644 if (global.uid != 0) {
645 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200646 err_code |= ERR_ALERT;
647 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200648 }
649 errno = 0;
650 ha_user = getpwnam(args[1]);
651 if (ha_user != NULL) {
652 global.uid = (int)ha_user->pw_uid;
653 }
654 else {
655 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 +0200656 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200657 }
658 }
659 else if (!strcmp(args[0], "group")) {
660 struct group *ha_group;
661 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200662 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200663 err_code |= ERR_ALERT;
664 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200665 }
666 errno = 0;
667 ha_group = getgrnam(args[1]);
668 if (ha_group != NULL) {
669 global.gid = (int)ha_group->gr_gid;
670 }
671 else {
672 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 +0200673 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200674 }
675 }
676 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200677 else if (!strcmp(args[0], "nbproc")) {
678 if (global.nbproc != 0) {
679 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200680 err_code |= ERR_ALERT;
681 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
683 if (*(args[1]) == 0) {
684 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200685 err_code |= ERR_ALERT | ERR_FATAL;
686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200687 }
688 global.nbproc = atol(args[1]);
689 }
690 else if (!strcmp(args[0], "maxconn")) {
691 if (global.maxconn != 0) {
692 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT;
694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200695 }
696 if (*(args[1]) == 0) {
697 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200698 err_code |= ERR_ALERT | ERR_FATAL;
699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 }
701 global.maxconn = atol(args[1]);
702#ifdef SYSTEM_MAXCONN
703 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
704 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);
705 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200706 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200707 }
708#endif /* SYSTEM_MAXCONN */
709 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200710 else if (!strcmp(args[0], "maxconnrate")) {
711 if (global.cps_lim != 0) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
713 err_code |= ERR_ALERT;
714 goto out;
715 }
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
720 }
721 global.cps_lim = atol(args[1]);
722 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100723 else if (!strcmp(args[0], "maxpipes")) {
724 if (global.maxpipes != 0) {
725 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200726 err_code |= ERR_ALERT;
727 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100728 }
729 if (*(args[1]) == 0) {
730 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200731 err_code |= ERR_ALERT | ERR_FATAL;
732 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100733 }
734 global.maxpipes = atol(args[1]);
735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200736 else if (!strcmp(args[0], "ulimit-n")) {
737 if (global.rlimit_nofile != 0) {
738 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200739 err_code |= ERR_ALERT;
740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200741 }
742 if (*(args[1]) == 0) {
743 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200744 err_code |= ERR_ALERT | ERR_FATAL;
745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200746 }
747 global.rlimit_nofile = atol(args[1]);
748 }
749 else if (!strcmp(args[0], "chroot")) {
750 if (global.chroot != NULL) {
751 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200752 err_code |= ERR_ALERT;
753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 }
755 if (*(args[1]) == 0) {
756 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200759 }
760 global.chroot = strdup(args[1]);
761 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200762 else if (!strcmp(args[0], "description")) {
763 int i, len=0;
764 char *d;
765
766 if (!*args[1]) {
767 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
768 file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772
773 for(i=1; *args[i]; i++)
774 len += strlen(args[i])+1;
775
776 if (global.desc)
777 free(global.desc);
778
779 global.desc = d = (char *)calloc(1, len);
780
781 d += sprintf(d, "%s", args[1]);
782 for(i=2; *args[i]; i++)
783 d += sprintf(d, " %s", args[i]);
784 }
785 else if (!strcmp(args[0], "node")) {
786 int i;
787 char c;
788
789 for (i=0; args[1][i]; i++) {
790 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100791 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
792 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200793 break;
794 }
795
796 if (!i || args[1][i]) {
797 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
798 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
799 file, linenum, args[0]);
800 err_code |= ERR_ALERT | ERR_FATAL;
801 goto out;
802 }
803
804 if (global.node)
805 free(global.node);
806
807 global.node = strdup(args[1]);
808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200809 else if (!strcmp(args[0], "pidfile")) {
810 if (global.pidfile != NULL) {
811 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200812 err_code |= ERR_ALERT;
813 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200814 }
815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 }
820 global.pidfile = strdup(args[1]);
821 }
Emeric Bruned760922010-10-22 17:59:25 +0200822 else if (!strcmp(args[0], "unix-bind")) {
823 int cur_arg = 1;
824 while (*(args[cur_arg])) {
825 if (!strcmp(args[cur_arg], "prefix")) {
826 if (global.unix_bind.prefix != NULL) {
827 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
828 err_code |= ERR_ALERT;
829 cur_arg += 2;
830 continue;
831 }
832
833 if (*(args[cur_arg+1]) == 0) {
834 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838 global.unix_bind.prefix = strdup(args[cur_arg+1]);
839 cur_arg += 2;
840 continue;
841 }
842
843 if (!strcmp(args[cur_arg], "mode")) {
844
845 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
846 cur_arg += 2;
847 continue;
848 }
849
850 if (!strcmp(args[cur_arg], "uid")) {
851
852 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
853 cur_arg += 2;
854 continue;
855 }
856
857 if (!strcmp(args[cur_arg], "gid")) {
858
859 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
860 cur_arg += 2;
861 continue;
862 }
863
864 if (!strcmp(args[cur_arg], "user")) {
865 struct passwd *user;
866
867 user = getpwnam(args[cur_arg + 1]);
868 if (!user) {
869 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
870 file, linenum, args[0], args[cur_arg + 1 ]);
871 err_code |= ERR_ALERT | ERR_FATAL;
872 goto out;
873 }
874
875 global.unix_bind.ux.uid = user->pw_uid;
876 cur_arg += 2;
877 continue;
878 }
879
880 if (!strcmp(args[cur_arg], "group")) {
881 struct group *group;
882
883 group = getgrnam(args[cur_arg + 1]);
884 if (!group) {
885 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
886 file, linenum, args[0], args[cur_arg + 1 ]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890
891 global.unix_bind.ux.gid = group->gr_gid;
892 cur_arg += 2;
893 continue;
894 }
895
Willy Tarreaub48f9582011-09-05 01:17:06 +0200896 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200897 file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901 }
William Lallemand0f99e342011-10-12 17:50:54 +0200902 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
903 /* delete previous herited or defined syslog servers */
904 struct logsrv *back;
905 struct logsrv *tmp;
906
907 if (*(args[1]) != 0) {
908 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
909 err_code |= ERR_ALERT | ERR_FATAL;
910 goto out;
911 }
912
913 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
914 LIST_DEL(&tmp->list);
915 free(tmp);
916 }
917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200919 struct logsrv *logsrv;
920
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 if (*(args[1]) == 0 || *(args[2]) == 0) {
922 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925 }
William Lallemand0f99e342011-10-12 17:50:54 +0200926
927 logsrv = calloc(1, sizeof(struct logsrv));
928
929 logsrv->facility = get_log_facility(args[2]);
930 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200932 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200933 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 }
935
William Lallemand0f99e342011-10-12 17:50:54 +0200936 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200938 logsrv->level = get_log_level(args[3]);
939 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200941 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200942 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 }
944 }
945
William Lallemand0f99e342011-10-12 17:50:54 +0200946 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200947 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200948 logsrv->minlvl = get_log_level(args[4]);
949 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200950 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200951 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200952 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200953 }
954 }
955
Robert Tsai81ae1952007-12-05 10:47:29 +0100956 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100957 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100958 if (!sk) {
959 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100960 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100961 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200962 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100963 goto out;
964 }
William Lallemand0f99e342011-10-12 17:50:54 +0200965 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100966 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100967 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100968 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100969 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
970 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200971 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100972 goto out;
973 }
William Lallemand0f99e342011-10-12 17:50:54 +0200974 logsrv->addr = *sk;
975 if (!get_host_port(&logsrv->addr))
976 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978
William Lallemand0f99e342011-10-12 17:50:54 +0200979 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200980 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100981 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
982 char *name;
983 int len;
984
985 if (global.log_send_hostname != NULL) {
986 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
987 err_code |= ERR_ALERT;
988 goto out;
989 }
990
991 if (*(args[1]))
992 name = args[1];
993 else
994 name = hostname;
995
996 len = strlen(name);
997
998 /* We'll add a space after the name to respect the log format */
999 free(global.log_send_hostname);
1000 global.log_send_hostname = malloc(len + 2);
1001 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1002 }
Kevinm48936af2010-12-22 16:08:21 +00001003 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1004 if (*(args[1]) == 0) {
1005 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1006 err_code |= ERR_ALERT | ERR_FATAL;
1007 goto out;
1008 }
1009 free(global.log_tag);
1010 global.log_tag = strdup(args[1]);
1011 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001012 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1013 if (global.spread_checks != 0) {
1014 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001015 err_code |= ERR_ALERT;
1016 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001017 }
1018 if (*(args[1]) == 0) {
1019 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001022 }
1023 global.spread_checks = atol(args[1]);
1024 if (global.spread_checks < 0 || global.spread_checks > 50) {
1025 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001026 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001028 }
1029 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001030 struct cfg_kw_list *kwl;
1031 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001032 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001033
1034 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1035 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1036 if (kwl->kw[index].section != CFG_GLOBAL)
1037 continue;
1038 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1039 /* prepare error message just in case */
David du Colombier7af46052012-05-16 14:16:48 +02001040 snprintf(trash, trashlen,
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001041 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001042 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001043 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001044 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001046 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001047 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001048 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001049 err_code |= ERR_WARN;
1050 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001051 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001052 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001053 }
1054 }
1055 }
1056
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001058 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001060
Willy Tarreau058e9072009-07-20 09:30:05 +02001061 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001062 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001063 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064}
1065
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001066void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001068 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001069 defproxy.mode = PR_MODE_TCP;
1070 defproxy.state = PR_STNEW;
1071 defproxy.maxconn = cfg_maxpconn;
1072 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001073
1074 defproxy.defsrv.inter = DEF_CHKINTR;
1075 defproxy.defsrv.fastinter = 0;
1076 defproxy.defsrv.downinter = 0;
1077 defproxy.defsrv.rise = DEF_RISETIME;
1078 defproxy.defsrv.fall = DEF_FALLTIME;
1079 defproxy.defsrv.check_port = 0;
1080 defproxy.defsrv.maxqueue = 0;
1081 defproxy.defsrv.minconn = 0;
1082 defproxy.defsrv.maxconn = 0;
1083 defproxy.defsrv.slowstart = 0;
1084 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1085 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1086 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087}
1088
Willy Tarreauade5ec42010-01-28 19:33:49 +01001089
1090static int create_cond_regex_rule(const char *file, int line,
1091 struct proxy *px, int dir, int action, int flags,
1092 const char *cmd, const char *reg, const char *repl,
1093 const char **cond_start)
1094{
1095 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001096 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001097 const char *err;
1098 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001099 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001100
1101 if (px == &defproxy) {
1102 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1103 err_code |= ERR_ALERT | ERR_FATAL;
1104 goto err;
1105 }
1106
1107 if (*reg == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto err;
1111 }
1112
1113 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1114 err_code |= ERR_WARN;
1115
Willy Tarreau5321c422010-01-28 20:35:13 +01001116 if (cond_start &&
1117 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001118 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1119 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1120 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto err;
1123 }
1124 }
1125 else if (cond_start && **cond_start) {
1126 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1127 file, line, cmd, *cond_start);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto err;
1130 }
1131
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001132 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001133 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001134 else
1135 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001136
Willy Tarreauade5ec42010-01-28 19:33:49 +01001137 preg = calloc(1, sizeof(regex_t));
1138 if (!preg) {
1139 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1140 err_code = ERR_ALERT | ERR_FATAL;
1141 goto err;
1142 }
1143
1144 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1145 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1146 err_code = ERR_ALERT | ERR_FATAL;
1147 goto err;
1148 }
1149
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001150 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001151 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001152 if (repl && err) {
1153 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1154 file, line, cmd, *err);
1155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto err;
1157 }
1158
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001159 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001160 err_code |= ERR_WARN;
1161
Willy Tarreauf4068b62012-05-08 17:37:49 +02001162 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001163 return err_code;
1164 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001165 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001166 free(preg);
1167 return err_code;
1168}
1169
Willy Tarreaubaaee002006-06-26 02:48:02 +02001170/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001171 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001172 * Returns the error code, 0 if OK, or any combination of :
1173 * - ERR_ABORT: must abort ASAP
1174 * - ERR_FATAL: we can continue parsing but not start the service
1175 * - ERR_WARN: a warning has been emitted
1176 * - ERR_ALERT: an alert has been emitted
1177 * Only the two first ones can stop processing, the two others are just
1178 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001179 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001180int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1181{
1182 static struct peers *curpeers = NULL;
1183 struct peer *newpeer = NULL;
1184 const char *err;
1185 int err_code = 0;
1186
1187 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1188
1189 err = invalid_char(args[1]);
1190 if (err) {
1191 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1192 file, linenum, *err, args[0], args[1]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 }
1195
1196 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1197 /*
1198 * If there are two proxies with the same name only following
1199 * combinations are allowed:
1200 */
1201 if (strcmp(curpeers->id, args[1]) == 0) {
1202 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1203 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1204 err_code |= ERR_WARN;
1205 }
1206 }
1207
1208 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1209 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1210 err_code |= ERR_ALERT | ERR_ABORT;
1211 goto out;
1212 }
1213
1214 curpeers->next = peers;
1215 peers = curpeers;
1216 curpeers->conf.file = file;
1217 curpeers->conf.line = linenum;
1218 curpeers->last_change = now.tv_sec;
1219 curpeers->id = strdup(args[1]);
1220 }
1221 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1222 char *rport, *raddr;
1223 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001224 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001225
1226 if (!*args[2]) {
1227 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1228 file, linenum, args[0]);
1229 err_code |= ERR_ALERT | ERR_FATAL;
1230 goto out;
1231 }
1232
1233 err = invalid_char(args[1]);
1234 if (err) {
1235 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1236 file, linenum, *err, args[1]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240
1241 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1242 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1243 err_code |= ERR_ALERT | ERR_ABORT;
1244 goto out;
1245 }
1246
1247 /* the peers are linked backwards first */
1248 curpeers->count++;
1249 newpeer->next = curpeers->remote;
1250 curpeers->remote = newpeer;
1251 newpeer->peers = curpeers;
1252 newpeer->conf.file = file;
1253 newpeer->conf.line = linenum;
1254
1255 newpeer->last_change = now.tv_sec;
1256 newpeer->id = strdup(args[1]);
1257
1258 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001259 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001260 if (rport) {
1261 *rport++ = 0;
1262 realport = atol(rport);
1263 }
1264 if (!realport) {
1265 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
1269
Willy Tarreaufab5a432011-03-04 15:31:53 +01001270 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001271 free(raddr);
1272 if (!sk) {
1273 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1274 err_code |= ERR_ALERT | ERR_FATAL;
1275 goto out;
1276 }
1277 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001278 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02001279 newpeer->data = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001280 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001281
1282 if (!sk) {
1283 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1284 file, linenum, newpeer->addr.ss_family, args[2]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001289 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001290
1291 if (strcmp(newpeer->id, localpeer) == 0) {
1292 /* Current is local peer, it define a frontend */
1293 newpeer->local = 1;
1294
1295 if (!curpeers->peers_fe) {
1296 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1298 err_code |= ERR_ALERT | ERR_ABORT;
1299 goto out;
1300 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001301
Willy Tarreau237250c2011-07-29 01:49:03 +02001302 init_new_proxy(curpeers->peers_fe);
1303 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001304
1305 curpeers->peers_fe->last_change = now.tv_sec;
1306 curpeers->peers_fe->id = strdup(args[1]);
1307 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001308 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001309 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1310 curpeers->peers_fe->timeout.connect = 5000;
1311 curpeers->peers_fe->accept = peer_accept;
1312 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001313 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001314 err_code |= ERR_FATAL;
1315 goto out;
1316 }
1317 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1318 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1319 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1320 curpeers->peers_fe->listen->accept = session_accept;
1321 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1322 curpeers->peers_fe->listen->handler = process_session;
1323 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001324 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1325 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001326 }
1327 }
1328 } /* neither "peer" nor "peers" */
1329 else if (*args[0] != 0) {
1330 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1331 err_code |= ERR_ALERT | ERR_FATAL;
1332 goto out;
1333 }
1334
1335out:
1336 return err_code;
1337}
1338
1339
Willy Tarreau3842f002009-06-14 11:39:52 +02001340int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341{
1342 static struct proxy *curproxy = NULL;
1343 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001344 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001345 int rc;
1346 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001347 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001348 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001349 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001350 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351
Willy Tarreau977b8e42006-12-29 14:19:17 +01001352 if (!strcmp(args[0], "listen"))
1353 rc = PR_CAP_LISTEN;
1354 else if (!strcmp(args[0], "frontend"))
1355 rc = PR_CAP_FE | PR_CAP_RS;
1356 else if (!strcmp(args[0], "backend"))
1357 rc = PR_CAP_BE | PR_CAP_RS;
1358 else if (!strcmp(args[0], "ruleset"))
1359 rc = PR_CAP_RS;
1360 else
1361 rc = PR_CAP_NONE;
1362
1363 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 if (!*args[1]) {
1365 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1366 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1367 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001368 err_code |= ERR_ALERT | ERR_ABORT;
1369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001371
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001372 err = invalid_char(args[1]);
1373 if (err) {
1374 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1375 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001376 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001377 }
1378
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001379 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1380 /*
1381 * If there are two proxies with the same name only following
1382 * combinations are allowed:
1383 *
1384 * listen backend frontend ruleset
1385 * listen - - - -
1386 * backend - - OK -
1387 * frontend - OK - -
1388 * ruleset - - - -
1389 */
1390
1391 if (!strcmp(curproxy->id, args[1]) &&
1392 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1393 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001394 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1395 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1396 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001397 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001398 }
1399 }
1400
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1402 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001403 err_code |= ERR_ALERT | ERR_ABORT;
1404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001406
Willy Tarreau97cb7802010-01-03 20:23:58 +01001407 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 curproxy->next = proxy;
1409 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001410 curproxy->conf.file = file;
1411 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001412 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001414 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415
1416 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001417 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001418 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001419 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001420 err_code |= ERR_FATAL;
1421 goto out;
1422 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001423 new = curproxy->listen;
1424 while (new != last) {
1425 new->conf.file = file;
1426 new->conf.line = linenum;
1427 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001428 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001429 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 }
1431
1432 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001433 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001434 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001435
Willy Tarreaubaaee002006-06-26 02:48:02 +02001436 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001437 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001438 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001439 curproxy->no_options = defproxy.no_options;
1440 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001441 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001442 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001443 curproxy->except_net = defproxy.except_net;
1444 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001445 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001446 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001448 if (defproxy.fwdfor_hdr_len) {
1449 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1450 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1451 }
1452
Willy Tarreaub86db342009-11-30 11:50:16 +01001453 if (defproxy.orgto_hdr_len) {
1454 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1455 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1456 }
1457
Mark Lamourinec2247f02012-01-04 13:02:01 -05001458 if (defproxy.server_id_hdr_len) {
1459 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1460 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1461 }
1462
Willy Tarreau977b8e42006-12-29 14:19:17 +01001463 if (curproxy->cap & PR_CAP_FE) {
1464 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001465 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001466 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001467
1468 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001469 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1470 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001471
1472 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474
Willy Tarreau977b8e42006-12-29 14:19:17 +01001475 if (curproxy->cap & PR_CAP_BE) {
1476 curproxy->fullconn = defproxy.fullconn;
1477 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001479 if (defproxy.check_req) {
1480 curproxy->check_req = calloc(1, defproxy.check_len);
1481 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1482 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001483 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001484
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001485 if (defproxy.expect_str) {
1486 curproxy->expect_str = strdup(defproxy.expect_str);
1487 if (defproxy.expect_regex) {
1488 /* note: this regex is known to be valid */
1489 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1490 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1491 }
1492 }
1493
Willy Tarreau67402132012-05-31 20:40:20 +02001494 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495 if (defproxy.cookie_name)
1496 curproxy->cookie_name = strdup(defproxy.cookie_name);
1497 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001498 if (defproxy.cookie_domain)
1499 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001500
Willy Tarreau31936852010-10-06 16:59:56 +02001501 if (defproxy.cookie_maxidle)
1502 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1503
1504 if (defproxy.cookie_maxlife)
1505 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1506
Emeric Brun647caf12009-06-30 17:57:00 +02001507 if (defproxy.rdp_cookie_name)
1508 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1509 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1510
Willy Tarreau01732802007-11-01 22:48:15 +01001511 if (defproxy.url_param_name)
1512 curproxy->url_param_name = strdup(defproxy.url_param_name);
1513 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001514
Benoitaffb4812009-03-25 13:02:10 +01001515 if (defproxy.hh_name)
1516 curproxy->hh_name = strdup(defproxy.hh_name);
1517 curproxy->hh_len = defproxy.hh_len;
1518 curproxy->hh_match_domain = defproxy.hh_match_domain;
1519
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001520 if (defproxy.iface_name)
1521 curproxy->iface_name = strdup(defproxy.iface_name);
1522 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001524
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001525 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001526 if (defproxy.capture_name)
1527 curproxy->capture_name = strdup(defproxy.capture_name);
1528 curproxy->capture_namelen = defproxy.capture_namelen;
1529 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531
Willy Tarreau977b8e42006-12-29 14:19:17 +01001532 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001533 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001534 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001535 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001536 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001537 curproxy->uri_auth = defproxy.uri_auth;
1538 curproxy->mon_net = defproxy.mon_net;
1539 curproxy->mon_mask = defproxy.mon_mask;
1540 if (defproxy.monitor_uri)
1541 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1542 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001543 if (defproxy.defbe.name)
1544 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001545
1546 /* get either a pointer to the logformat string or a copy of it */
1547 curproxy->logformat_string = defproxy.logformat_string;
1548 if (curproxy->logformat_string &&
1549 curproxy->logformat_string != default_http_log_format &&
1550 curproxy->logformat_string != default_tcp_log_format &&
1551 curproxy->logformat_string != clf_http_log_format)
1552 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001553 }
1554
1555 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001556 curproxy->timeout.connect = defproxy.timeout.connect;
1557 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001558 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001559 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001560 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001561 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001562 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001563 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001564 curproxy->source_addr = defproxy.source_addr;
1565 }
1566
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001568
1569 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001570 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001571 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001572 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001573 LIST_INIT(&node->list);
1574 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1575 }
1576
Willy Tarreau196729e2012-05-31 19:30:26 +02001577 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1578 if (curproxy->uniqueid_format_string)
1579 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001580
1581 /* copy default header unique id */
1582 if (defproxy.header_unique_id)
1583 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001586 curproxy->conf.used_listener_id = EB_ROOT;
1587 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001588
Willy Tarreau93893792009-07-23 13:19:11 +02001589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 }
1591 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1592 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001593 /* FIXME-20070101: we should do this too at the end of the
1594 * config parsing to free all default values.
1595 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001596 free(defproxy.check_req);
1597 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001598 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001599 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001600 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001601 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001602 free(defproxy.capture_name);
1603 free(defproxy.monitor_uri);
1604 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001605 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001606 free(defproxy.fwdfor_hdr_name);
1607 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001608 free(defproxy.orgto_hdr_name);
1609 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001610 free(defproxy.server_id_hdr_name);
1611 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001612 free(defproxy.expect_str);
1613 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001614
Willy Tarreau39b06652012-06-01 10:58:06 +02001615 if (defproxy.logformat_string != default_http_log_format &&
1616 defproxy.logformat_string != default_tcp_log_format &&
1617 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001618 free(defproxy.logformat_string);
1619
1620 free(defproxy.uniqueid_format_string);
1621
Willy Tarreaua534fea2008-08-03 12:19:50 +02001622 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001623 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001624
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 /* we cannot free uri_auth because it might already be used */
1626 init_default_instance();
1627 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001628 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001629 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 }
1631 else if (curproxy == NULL) {
1632 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001633 err_code |= ERR_ALERT | ERR_FATAL;
1634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 }
1636
Willy Tarreau977b8e42006-12-29 14:19:17 +01001637
1638 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001640 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001641 int cur_arg;
1642
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 if (curproxy == &defproxy) {
1644 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001647 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001648 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001649 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650
Emeric Bruned760922010-10-22 17:59:25 +02001651 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001652 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
1655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001657
1658 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001659
1660 /* NOTE: the following line might create several listeners if there
1661 * are comma-separated IPs or port ranges. So all further processing
1662 * will have to be applied to all listeners created after last_listen.
1663 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001664 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001665 err_code |= ERR_ALERT | ERR_FATAL;
1666 goto out;
1667 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001668
Willy Tarreau90a570f2009-10-04 20:54:54 +02001669 new_listen = curproxy->listen;
1670 while (new_listen != last_listen) {
1671 new_listen->conf.file = file;
1672 new_listen->conf.line = linenum;
1673 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001674 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001675 }
1676
Emeric Bruned760922010-10-22 17:59:25 +02001677 /* Set default global rights and owner for unix bind */
1678 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1679 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1680 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001681 cur_arg = 2;
1682 while (*(args[cur_arg])) {
1683 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1684#ifdef SO_BINDTODEVICE
1685 struct listener *l;
1686
Emeric Bruned760922010-10-22 17:59:25 +02001687 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1688 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1689 file, linenum, args[0], args[cur_arg]);
1690 err_code |= ERR_ALERT | ERR_FATAL;
1691 goto out;
1692 }
1693
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001694 if (!*args[cur_arg + 1]) {
1695 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1696 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
1698 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001699 }
1700
1701 for (l = curproxy->listen; l != last_listen; l = l->next)
1702 l->interface = strdup(args[cur_arg + 1]);
1703
1704 global.last_checks |= LSTCHK_NETADM;
1705
1706 cur_arg += 2;
1707 continue;
1708#else
1709 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1710 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001713#endif
1714 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001715 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1716#ifdef TCP_MAXSEG
1717 struct listener *l;
1718 int mss;
1719
Emeric Bruned760922010-10-22 17:59:25 +02001720 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1721 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1722 file, linenum, args[0], args[cur_arg]);
1723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
1725 }
1726
Willy Tarreaube1b9182009-06-14 18:48:19 +02001727 if (!*args[cur_arg + 1]) {
1728 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1729 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001730 err_code |= ERR_ALERT | ERR_FATAL;
1731 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001732 }
1733
Willy Tarreau48a7e722010-12-24 15:26:39 +01001734 mss = atoi(args[cur_arg + 1]);
1735 if (!mss || abs(mss) > 65535) {
1736 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001738 err_code |= ERR_ALERT | ERR_FATAL;
1739 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001740 }
1741
1742 for (l = curproxy->listen; l != last_listen; l = l->next)
1743 l->maxseg = mss;
1744
1745 cur_arg += 2;
1746 continue;
1747#else
1748 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1749 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_FATAL;
1751 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001752#endif
1753 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001754
1755 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1756#ifdef TCP_DEFER_ACCEPT
1757 struct listener *l;
1758
1759 for (l = curproxy->listen; l != last_listen; l = l->next)
1760 l->options |= LI_O_DEF_ACCEPT;
1761
1762 cur_arg ++;
1763 continue;
1764#else
1765 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1766 file, linenum, args[0], args[cur_arg]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769#endif
1770 }
1771
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001772 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001773#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001774 struct listener *l;
1775
Emeric Bruned760922010-10-22 17:59:25 +02001776 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1777 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1778 file, linenum, args[0], args[cur_arg]);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001783 for (l = curproxy->listen; l != last_listen; l = l->next)
1784 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001785
1786 cur_arg ++;
1787 continue;
1788#else
1789 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1790 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001791 err_code |= ERR_ALERT | ERR_FATAL;
1792 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001793#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001794 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001795
Willy Tarreau8a956912010-10-15 14:27:08 +02001796 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1797 struct listener *l;
1798
1799 for (l = curproxy->listen; l != last_listen; l = l->next)
1800 l->options |= LI_O_ACC_PROXY;
1801
1802 cur_arg ++;
1803 continue;
1804 }
1805
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001806 if (!strcmp(args[cur_arg], "name")) {
1807 struct listener *l;
1808
1809 for (l = curproxy->listen; l != last_listen; l = l->next)
1810 l->name = strdup(args[cur_arg + 1]);
1811
1812 cur_arg += 2;
1813 continue;
1814 }
1815
1816 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001817 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001818 struct listener *l;
1819
1820 if (curproxy->listen->next != last_listen) {
1821 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1822 file, linenum, args[cur_arg]);
1823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
1825 }
1826
1827 if (!*args[cur_arg + 1]) {
1828 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1829 file, linenum, args[cur_arg]);
1830 err_code |= ERR_ALERT | ERR_FATAL;
1831 goto out;
1832 }
1833
1834 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001835 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001836
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001837 if (curproxy->listen->luid <= 0) {
1838 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001839 file, linenum);
1840 err_code |= ERR_ALERT | ERR_FATAL;
1841 goto out;
1842 }
1843
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001844 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1845 if (node) {
1846 l = container_of(node, struct listener, conf.id);
1847 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1848 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1849 err_code |= ERR_ALERT | ERR_FATAL;
1850 goto out;
1851 }
1852 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1853
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001854 cur_arg += 2;
1855 continue;
1856 }
1857
Emeric Bruned760922010-10-22 17:59:25 +02001858 if (!strcmp(args[cur_arg], "mode")) {
1859
1860 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1861 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1862 file, linenum, args[0], args[cur_arg]);
1863 err_code |= ERR_ALERT | ERR_FATAL;
1864 goto out;
1865 }
1866
1867 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1868
1869 cur_arg += 2;
1870 continue;
1871 }
1872
1873 if (!strcmp(args[cur_arg], "uid")) {
1874
1875 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1876 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1877 file, linenum, args[0], args[cur_arg]);
1878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
1880 }
1881
1882 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1883 cur_arg += 2;
1884 continue;
1885 }
1886
1887 if (!strcmp(args[cur_arg], "gid")) {
1888
1889 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1890 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1891 file, linenum, args[0], args[cur_arg]);
1892 err_code |= ERR_ALERT | ERR_FATAL;
1893 goto out;
1894 }
1895
1896 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1897 cur_arg += 2;
1898 continue;
1899 }
1900
1901 if (!strcmp(args[cur_arg], "user")) {
1902 struct passwd *user;
1903
1904 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1905 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1906 file, linenum, args[0], args[cur_arg]);
1907 err_code |= ERR_ALERT | ERR_FATAL;
1908 goto out;
1909 }
1910 user = getpwnam(args[cur_arg + 1]);
1911 if (!user) {
1912 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1913 file, linenum, args[0], args[cur_arg + 1 ]);
1914 err_code |= ERR_ALERT | ERR_FATAL;
1915 goto out;
1916 }
1917
1918 curproxy->listen->perm.ux.uid = user->pw_uid;
1919 cur_arg += 2;
1920 continue;
1921 }
1922
1923 if (!strcmp(args[cur_arg], "group")) {
1924 struct group *group;
1925
1926 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1927 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1928 file, linenum, args[0], args[cur_arg]);
1929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
1931 }
1932 group = getgrnam(args[cur_arg + 1]);
1933 if (!group) {
1934 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1935 file, linenum, args[0], args[cur_arg + 1 ]);
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939
1940 curproxy->listen->perm.ux.gid = group->gr_gid;
1941 cur_arg += 2;
1942 continue;
1943 }
1944
Willy Tarreaub48f9582011-09-05 01:17:06 +02001945 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 +01001946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
1948 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001949 }
Willy Tarreau93893792009-07-23 13:19:11 +02001950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001951 }
1952 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1953 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1954 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1955 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001956 err_code |= ERR_ALERT | ERR_FATAL;
1957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001959 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001961
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 /* flush useless bits */
1963 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001966 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001967 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001968 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969
Willy Tarreau1c47f852006-07-09 08:22:27 +02001970 if (!*args[1]) {
1971 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1972 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_ALERT | ERR_FATAL;
1974 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001975 }
1976
Willy Tarreaua534fea2008-08-03 12:19:50 +02001977 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001978 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001979 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001980 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001981 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1982
Willy Tarreau93893792009-07-23 13:19:11 +02001983 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001984 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1986 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1987 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1988 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1989 else {
1990 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001993 }
1994 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001995 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001996 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001997
1998 if (curproxy == &defproxy) {
1999 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2000 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002003 }
2004
2005 if (!*args[1]) {
2006 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2007 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002008 err_code |= ERR_ALERT | ERR_FATAL;
2009 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002010 }
2011
2012 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002013 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002014
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002015 if (curproxy->uuid <= 0) {
2016 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002017 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002020 }
2021
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002022 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2023 if (node) {
2024 struct proxy *target = container_of(node, struct proxy, conf.id);
2025 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2026 file, linenum, proxy_type_str(curproxy), curproxy->id,
2027 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
2030 }
2031 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002032 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002033 else if (!strcmp(args[0], "description")) {
2034 int i, len=0;
2035 char *d;
2036
Cyril Bonté99ed3272010-01-24 23:29:44 +01002037 if (curproxy == &defproxy) {
2038 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2039 file, linenum, args[0]);
2040 err_code |= ERR_ALERT | ERR_FATAL;
2041 goto out;
2042 }
2043
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002044 if (!*args[1]) {
2045 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2046 file, linenum, args[0]);
2047 return -1;
2048 }
2049
2050 for(i=1; *args[i]; i++)
2051 len += strlen(args[i])+1;
2052
2053 d = (char *)calloc(1, len);
2054 curproxy->desc = d;
2055
2056 d += sprintf(d, "%s", args[1]);
2057 for(i=2; *args[i]; i++)
2058 d += sprintf(d, " %s", args[i]);
2059
2060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002061 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2062 curproxy->state = PR_STSTOPPED;
2063 }
2064 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2065 curproxy->state = PR_STNEW;
2066 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002067 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2068 int cur_arg = 1;
2069 unsigned int set = 0;
2070
2071 while (*args[cur_arg]) {
2072 int u;
2073 if (strcmp(args[cur_arg], "all") == 0) {
2074 set = 0;
2075 break;
2076 }
2077 else if (strcmp(args[cur_arg], "odd") == 0) {
2078 set |= 0x55555555;
2079 }
2080 else if (strcmp(args[cur_arg], "even") == 0) {
2081 set |= 0xAAAAAAAA;
2082 }
2083 else {
2084 u = str2uic(args[cur_arg]);
2085 if (u < 1 || u > 32) {
2086 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2087 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002088 err_code |= ERR_ALERT | ERR_FATAL;
2089 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002090 }
2091 if (u > global.nbproc) {
2092 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002095 }
2096 set |= 1 << (u - 1);
2097 }
2098 cur_arg++;
2099 }
2100 curproxy->bind_proc = set;
2101 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002102 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002103 if (curproxy == &defproxy) {
2104 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002107 }
2108
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002109 err = invalid_char(args[1]);
2110 if (err) {
2111 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2112 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002113 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002114 }
2115
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002116 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2117 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2118 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002119 err_code |= ERR_ALERT | ERR_FATAL;
2120 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002121 }
2122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2124 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125
Willy Tarreau977b8e42006-12-29 14:19:17 +01002126 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002127 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002128
Willy Tarreaubaaee002006-06-26 02:48:02 +02002129 if (*(args[1]) == 0) {
2130 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2131 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002132 err_code |= ERR_ALERT | ERR_FATAL;
2133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002135
Willy Tarreau67402132012-05-31 20:40:20 +02002136 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002137 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002138 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002139 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 curproxy->cookie_name = strdup(args[1]);
2141 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002142
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 cur_arg = 2;
2144 while (*(args[cur_arg])) {
2145 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002146 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002147 }
2148 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002149 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150 }
2151 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002152 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 }
2154 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002155 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 }
2157 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002158 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002160 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002161 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002163 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002164 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002166 else if (!strcmp(args[cur_arg], "httponly")) {
2167 curproxy->ck_opts |= PR_CK_HTTPONLY;
2168 }
2169 else if (!strcmp(args[cur_arg], "secure")) {
2170 curproxy->ck_opts |= PR_CK_SECURE;
2171 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002172 else if (!strcmp(args[cur_arg], "domain")) {
2173 if (!*args[cur_arg + 1]) {
2174 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2175 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002178 }
2179
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002180 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002181 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002182 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2183 " dots nor does not start with a dot."
2184 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002185 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002186 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002187 }
2188
2189 err = invalid_domainchar(args[cur_arg + 1]);
2190 if (err) {
2191 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2192 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002195 }
2196
Willy Tarreau68a897b2009-12-03 23:28:34 +01002197 if (!curproxy->cookie_domain) {
2198 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2199 } else {
2200 /* one domain was already specified, add another one by
2201 * building the string which will be returned along with
2202 * the cookie.
2203 */
2204 char *new_ptr;
2205 int new_len = strlen(curproxy->cookie_domain) +
2206 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2207 new_ptr = malloc(new_len);
2208 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2209 free(curproxy->cookie_domain);
2210 curproxy->cookie_domain = new_ptr;
2211 }
Willy Tarreau31936852010-10-06 16:59:56 +02002212 cur_arg++;
2213 }
2214 else if (!strcmp(args[cur_arg], "maxidle")) {
2215 unsigned int maxidle;
2216 const char *res;
2217
2218 if (!*args[cur_arg + 1]) {
2219 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2220 file, linenum, args[cur_arg]);
2221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
2223 }
2224
2225 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2226 if (res) {
2227 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2228 file, linenum, *res, args[cur_arg]);
2229 err_code |= ERR_ALERT | ERR_FATAL;
2230 goto out;
2231 }
2232 curproxy->cookie_maxidle = maxidle;
2233 cur_arg++;
2234 }
2235 else if (!strcmp(args[cur_arg], "maxlife")) {
2236 unsigned int maxlife;
2237 const char *res;
2238
2239 if (!*args[cur_arg + 1]) {
2240 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2241 file, linenum, args[cur_arg]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245
2246 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2247 if (res) {
2248 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2249 file, linenum, *res, args[cur_arg]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002254 cur_arg++;
2255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002256 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002257 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 +02002258 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
2262 cur_arg++;
2263 }
Willy Tarreau67402132012-05-31 20:40:20 +02002264 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002265 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2266 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002267 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 }
2269
Willy Tarreau67402132012-05-31 20:40:20 +02002270 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2272 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002275
Willy Tarreau67402132012-05-31 20:40:20 +02002276 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002277 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2278 file, linenum);
2279 err_code |= ERR_ALERT | ERR_FATAL;
2280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002282 else if (!strcmp(args[0], "persist")) { /* persist */
2283 if (*(args[1]) == 0) {
2284 Alert("parsing [%s:%d] : missing persist method.\n",
2285 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002288 }
2289
2290 if (!strncmp(args[1], "rdp-cookie", 10)) {
2291 curproxy->options2 |= PR_O2_RDPC_PRST;
2292
Emeric Brunb982a3d2010-01-04 15:45:53 +01002293 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002294 const char *beg, *end;
2295
2296 beg = args[1] + 11;
2297 end = strchr(beg, ')');
2298
2299 if (!end || end == beg) {
2300 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2301 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002304 }
2305
2306 free(curproxy->rdp_cookie_name);
2307 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2308 curproxy->rdp_cookie_len = end-beg;
2309 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002310 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002311 free(curproxy->rdp_cookie_name);
2312 curproxy->rdp_cookie_name = strdup("msts");
2313 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2314 }
2315 else { /* syntax */
2316 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2317 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002318 err_code |= ERR_ALERT | ERR_FATAL;
2319 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002320 }
2321 }
2322 else {
2323 Alert("parsing [%s:%d] : unknown persist method.\n",
2324 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002327 }
2328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002330 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002332 if (curproxy == &defproxy) {
2333 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2334 err_code |= ERR_ALERT | ERR_FATAL;
2335 goto out;
2336 }
2337
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002339 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002340
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002342 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 }
2347 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002348 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 curproxy->appsession_name = strdup(args[1]);
2350 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2351 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002352 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2353 if (err) {
2354 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2355 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002358 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002359 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002360
Willy Tarreau51041c72007-09-09 21:56:53 +02002361 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2362 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002363 err_code |= ERR_ALERT | ERR_ABORT;
2364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002366
2367 cur_arg = 6;
2368 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002369 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2370 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002371 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002372 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002373 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002374 } else if (!strcmp(args[cur_arg], "prefix")) {
2375 curproxy->options2 |= PR_O2_AS_PFX;
2376 } else if (!strcmp(args[cur_arg], "mode")) {
2377 if (!*args[cur_arg + 1]) {
2378 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2379 file, linenum, args[0], args[cur_arg]);
2380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
2382 }
2383
2384 cur_arg++;
2385 if (!strcmp(args[cur_arg], "query-string")) {
2386 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2387 curproxy->options2 |= PR_O2_AS_M_QS;
2388 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2389 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2390 curproxy->options2 |= PR_O2_AS_M_PP;
2391 } else {
2392 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
2395 }
2396 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002397 cur_arg++;
2398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 } /* Url App Session */
2400 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002401 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002402 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002403
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002405 if (curproxy == &defproxy) {
2406 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
2409 }
2410
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 if (*(args[4]) == 0) {
2412 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2413 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002414 err_code |= ERR_ALERT | ERR_FATAL;
2415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002417 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 curproxy->capture_name = strdup(args[2]);
2419 curproxy->capture_namelen = strlen(curproxy->capture_name);
2420 curproxy->capture_len = atol(args[4]);
2421 if (curproxy->capture_len >= CAPTURE_LEN) {
2422 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2423 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002424 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 curproxy->capture_len = CAPTURE_LEN - 1;
2426 }
2427 curproxy->to_log |= LW_COOKIE;
2428 }
2429 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2430 struct cap_hdr *hdr;
2431
2432 if (curproxy == &defproxy) {
2433 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 +02002434 err_code |= ERR_ALERT | ERR_FATAL;
2435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 }
2437
2438 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2439 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2440 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002441 err_code |= ERR_ALERT | ERR_FATAL;
2442 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443 }
2444
2445 hdr = calloc(sizeof(struct cap_hdr), 1);
2446 hdr->next = curproxy->req_cap;
2447 hdr->name = strdup(args[3]);
2448 hdr->namelen = strlen(args[3]);
2449 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002450 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 hdr->index = curproxy->nb_req_cap++;
2452 curproxy->req_cap = hdr;
2453 curproxy->to_log |= LW_REQHDR;
2454 }
2455 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2456 struct cap_hdr *hdr;
2457
2458 if (curproxy == &defproxy) {
2459 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 +02002460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 }
2463
2464 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2465 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2466 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 }
2470 hdr = calloc(sizeof(struct cap_hdr), 1);
2471 hdr->next = curproxy->rsp_cap;
2472 hdr->name = strdup(args[3]);
2473 hdr->namelen = strlen(args[3]);
2474 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002475 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 hdr->index = curproxy->nb_rsp_cap++;
2477 curproxy->rsp_cap = hdr;
2478 curproxy->to_log |= LW_RSPHDR;
2479 }
2480 else {
2481 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2482 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }
2486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002488 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002489 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002490
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 if (*(args[1]) == 0) {
2492 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2493 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002494 err_code |= ERR_ALERT | ERR_FATAL;
2495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002496 }
2497 curproxy->conn_retries = atol(args[1]);
2498 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002499 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002500 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002501
2502 if (curproxy == &defproxy) {
2503 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507
Willy Tarreauff011f22011-01-06 17:51:27 +01002508 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 +01002509 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2510 file, linenum, args[0]);
2511 err_code |= ERR_WARN;
2512 }
2513
Willy Tarreauff011f22011-01-06 17:51:27 +01002514 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002515
Willy Tarreauff011f22011-01-06 17:51:27 +01002516 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002517 err_code |= ERR_ALERT | ERR_ABORT;
2518 goto out;
2519 }
2520
Willy Tarreauff011f22011-01-06 17:51:27 +01002521 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2522 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002523 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002524 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2525 /* set the header name and length into the proxy structure */
2526 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2527 err_code |= ERR_WARN;
2528
2529 if (!*args[1]) {
2530 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2531 file, linenum, args[0]);
2532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
2534 }
2535
2536 /* set the desired header name */
2537 free(curproxy->server_id_hdr_name);
2538 curproxy->server_id_hdr_name = strdup(args[1]);
2539 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2540 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002541 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002542 if (curproxy == &defproxy) {
2543 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002546 }
2547
Willy Tarreauef6494c2010-01-28 17:12:36 +01002548 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002549 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002553 }
2554
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002555 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2556 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2557 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002560 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002561
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002562 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002563 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002564 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002565 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002566 struct redirect_rule *rule;
2567 int cur_arg;
2568 int type = REDIRECT_TYPE_NONE;
2569 int code = 302;
2570 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002571 char *cookie = NULL;
2572 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002573 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002574
Cyril Bonté99ed3272010-01-24 23:29:44 +01002575 if (curproxy == &defproxy) {
2576 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
2580
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002581 cur_arg = 1;
2582 while (*(args[cur_arg])) {
2583 if (!strcmp(args[cur_arg], "location")) {
2584 if (!*args[cur_arg + 1]) {
2585 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2586 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002589 }
2590
2591 type = REDIRECT_TYPE_LOCATION;
2592 cur_arg++;
2593 destination = args[cur_arg];
2594 }
2595 else if (!strcmp(args[cur_arg], "prefix")) {
2596 if (!*args[cur_arg + 1]) {
2597 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2598 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601 }
2602
2603 type = REDIRECT_TYPE_PREFIX;
2604 cur_arg++;
2605 destination = args[cur_arg];
2606 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002607 else if (!strcmp(args[cur_arg], "set-cookie")) {
2608 if (!*args[cur_arg + 1]) {
2609 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2610 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002613 }
2614
2615 cur_arg++;
2616 cookie = args[cur_arg];
2617 cookie_set = 1;
2618 }
2619 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2620 if (!*args[cur_arg + 1]) {
2621 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2622 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002625 }
2626
2627 cur_arg++;
2628 cookie = args[cur_arg];
2629 cookie_set = 0;
2630 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002631 else if (!strcmp(args[cur_arg],"code")) {
2632 if (!*args[cur_arg + 1]) {
2633 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2634 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002637 }
2638 cur_arg++;
2639 code = atol(args[cur_arg]);
2640 if (code < 301 || code > 303) {
2641 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2642 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002643 err_code |= ERR_ALERT | ERR_FATAL;
2644 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002645 }
2646 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002647 else if (!strcmp(args[cur_arg],"drop-query")) {
2648 flags |= REDIRECT_FLAG_DROP_QS;
2649 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002650 else if (!strcmp(args[cur_arg],"append-slash")) {
2651 flags |= REDIRECT_FLAG_APPEND_SLASH;
2652 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002653 else if (strcmp(args[cur_arg], "if") == 0 ||
2654 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002655 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002656 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002657 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2658 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002659 err_code |= ERR_ALERT | ERR_FATAL;
2660 goto out;
2661 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002662 break;
2663 }
2664 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002665 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 +02002666 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002669 }
2670 cur_arg++;
2671 }
2672
2673 if (type == REDIRECT_TYPE_NONE) {
2674 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2675 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002678 }
2679
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002680 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2681 rule->cond = cond;
2682 rule->rdr_str = strdup(destination);
2683 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002684 if (cookie) {
2685 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002686 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002687 */
2688 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002689 if (cookie_set) {
2690 rule->cookie_str = malloc(rule->cookie_len + 10);
2691 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2692 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2693 rule->cookie_len += 9;
2694 } else {
2695 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002696 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002697 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2698 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002699 }
2700 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002701 rule->type = type;
2702 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002703 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002704 LIST_INIT(&rule->list);
2705 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002706 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2707 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002708 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002709 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002710 struct switching_rule *rule;
2711
Willy Tarreaub099aca2008-10-12 17:26:37 +02002712 if (curproxy == &defproxy) {
2713 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002716 }
2717
Willy Tarreau55ea7572007-06-17 19:56:27 +02002718 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002720
2721 if (*(args[1]) == 0) {
2722 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002725 }
2726
Willy Tarreauef6494c2010-01-28 17:12:36 +01002727 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002728 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2729 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002730 err_code |= ERR_ALERT | ERR_FATAL;
2731 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002732 }
2733
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002734 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2735 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2736 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002739 }
2740
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002741 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002742
Willy Tarreau55ea7572007-06-17 19:56:27 +02002743 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2744 rule->cond = cond;
2745 rule->be.name = strdup(args[1]);
2746 LIST_INIT(&rule->list);
2747 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2748 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002749 else if (strcmp(args[0], "use-server") == 0) {
2750 struct server_rule *rule;
2751
2752 if (curproxy == &defproxy) {
2753 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
2756 }
2757
2758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2759 err_code |= ERR_WARN;
2760
2761 if (*(args[1]) == 0) {
2762 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
2766
2767 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2768 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2769 file, linenum, args[0]);
2770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
2772 }
2773
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002774 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2775 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2776 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
2779 }
2780
2781 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2782
2783 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2784 rule->cond = cond;
2785 rule->srv.name = strdup(args[1]);
2786 LIST_INIT(&rule->list);
2787 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2788 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2789 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002790 else if ((!strcmp(args[0], "force-persist")) ||
2791 (!strcmp(args[0], "ignore-persist"))) {
2792 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002793
2794 if (curproxy == &defproxy) {
2795 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2796 err_code |= ERR_ALERT | ERR_FATAL;
2797 goto out;
2798 }
2799
2800 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2801 err_code |= ERR_WARN;
2802
Willy Tarreauef6494c2010-01-28 17:12:36 +01002803 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002804 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2805 file, linenum, args[0]);
2806 err_code |= ERR_ALERT | ERR_FATAL;
2807 goto out;
2808 }
2809
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002810 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2811 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2812 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002817 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002818
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002819 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002820 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002821 if (!strcmp(args[0], "force-persist")) {
2822 rule->type = PERSIST_TYPE_FORCE;
2823 } else {
2824 rule->type = PERSIST_TYPE_IGNORE;
2825 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002826 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002827 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002828 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002829 else if (!strcmp(args[0], "stick-table")) {
2830 int myidx = 1;
2831
Emeric Brun32da3c42010-09-23 18:39:19 +02002832 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002833 curproxy->table.type = (unsigned int)-1;
2834 while (*args[myidx]) {
2835 const char *err;
2836
2837 if (strcmp(args[myidx], "size") == 0) {
2838 myidx++;
2839 if (!*(args[myidx])) {
2840 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2841 file, linenum, args[myidx-1]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
2845 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2846 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2847 file, linenum, *err, args[myidx-1]);
2848 err_code |= ERR_ALERT | ERR_FATAL;
2849 goto out;
2850 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002851 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002852 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002853 else if (strcmp(args[myidx], "peers") == 0) {
2854 myidx++;
2855 if (!*(args[myidx])) {
2856 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2857 file, linenum, args[myidx-1]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861 curproxy->table.peers.name = strdup(args[myidx++]);
2862 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002863 else if (strcmp(args[myidx], "expire") == 0) {
2864 myidx++;
2865 if (!*(args[myidx])) {
2866 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2867 file, linenum, args[myidx-1]);
2868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
2870 }
2871 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2872 if (err) {
2873 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2874 file, linenum, *err, args[myidx-1]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
2878 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002879 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002880 }
2881 else if (strcmp(args[myidx], "nopurge") == 0) {
2882 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002883 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002884 }
2885 else if (strcmp(args[myidx], "type") == 0) {
2886 myidx++;
2887 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2888 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2889 file, linenum, args[myidx]);
2890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
2892 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002893 /* myidx already points to next arg */
2894 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002895 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002896 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002897 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002898
2899 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002900 nw = args[myidx];
2901 while (*nw) {
2902 /* the "store" keyword supports a comma-separated list */
2903 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002904 sa = NULL; /* store arg */
2905 while (*nw && *nw != ',') {
2906 if (*nw == '(') {
2907 *nw = 0;
2908 sa = ++nw;
2909 while (*nw != ')') {
2910 if (!*nw) {
2911 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2912 file, linenum, args[0], cw);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916 nw++;
2917 }
2918 *nw = '\0';
2919 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002920 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002921 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002922 if (*nw)
2923 *nw++ = '\0';
2924 type = stktable_get_data_type(cw);
2925 if (type < 0) {
2926 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2927 file, linenum, args[0], cw);
2928 err_code |= ERR_ALERT | ERR_FATAL;
2929 goto out;
2930 }
Willy Tarreauac782882010-06-20 10:41:54 +02002931
2932 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2933 switch (err) {
2934 case PE_NONE: break;
2935 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002936 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2937 file, linenum, args[0], cw);
2938 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002939 break;
2940
2941 case PE_ARG_MISSING:
2942 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2943 file, linenum, args[0], cw);
2944 err_code |= ERR_ALERT | ERR_FATAL;
2945 goto out;
2946
2947 case PE_ARG_NOT_USED:
2948 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2949 file, linenum, args[0], cw);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952
2953 default:
2954 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2955 file, linenum, args[0], cw);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002958 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002959 }
2960 myidx++;
2961 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002962 else {
2963 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2964 file, linenum, args[myidx]);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002967 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002968 }
2969
2970 if (!curproxy->table.size) {
2971 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2972 file, linenum);
2973 err_code |= ERR_ALERT | ERR_FATAL;
2974 goto out;
2975 }
2976
2977 if (curproxy->table.type == (unsigned int)-1) {
2978 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2979 file, linenum);
2980 err_code |= ERR_ALERT | ERR_FATAL;
2981 goto out;
2982 }
2983 }
2984 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002985 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02002986 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002987 int myidx = 0;
2988 const char *name = NULL;
2989 int flags;
2990
2991 if (curproxy == &defproxy) {
2992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2993 err_code |= ERR_ALERT | ERR_FATAL;
2994 goto out;
2995 }
2996
2997 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2998 err_code |= ERR_WARN;
2999 goto out;
3000 }
3001
3002 myidx++;
3003 if ((strcmp(args[myidx], "store") == 0) ||
3004 (strcmp(args[myidx], "store-request") == 0)) {
3005 myidx++;
3006 flags = STK_IS_STORE;
3007 }
3008 else if (strcmp(args[myidx], "store-response") == 0) {
3009 myidx++;
3010 flags = STK_IS_STORE | STK_ON_RSP;
3011 }
3012 else if (strcmp(args[myidx], "match") == 0) {
3013 myidx++;
3014 flags = STK_IS_MATCH;
3015 }
3016 else if (strcmp(args[myidx], "on") == 0) {
3017 myidx++;
3018 flags = STK_IS_MATCH | STK_IS_STORE;
3019 }
3020 else {
3021 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3022 err_code |= ERR_ALERT | ERR_FATAL;
3023 goto out;
3024 }
3025
3026 if (*(args[myidx]) == 0) {
3027 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
3030 }
3031
David du Colombier7af46052012-05-16 14:16:48 +02003032 expr = sample_parse_expr(args, &myidx, trash, trashlen);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003033 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003034 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
3037 }
3038
3039 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003040 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003041 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3042 file, linenum, args[0], expr->fetch->kw);
3043 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003044 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 goto out;
3046 }
3047 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003048 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003049 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3050 file, linenum, args[0], expr->fetch->kw);
3051 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003052 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003053 goto out;
3054 }
3055 }
3056
3057 if (strcmp(args[myidx], "table") == 0) {
3058 myidx++;
3059 name = args[myidx++];
3060 }
3061
Willy Tarreauef6494c2010-01-28 17:12:36 +01003062 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003063 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3064 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3065 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003067 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003068 goto out;
3069 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003070 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003071 else if (*(args[myidx])) {
3072 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3073 file, linenum, args[0], args[myidx]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003075 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003076 goto out;
3077 }
Emeric Brun97679e72010-09-23 17:56:44 +02003078 if (flags & STK_ON_RSP)
3079 err_code |= warnif_cond_requires_req(cond, file, linenum);
3080 else
3081 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003082
Emeric Brunb982a3d2010-01-04 15:45:53 +01003083 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3084 rule->cond = cond;
3085 rule->expr = expr;
3086 rule->flags = flags;
3087 rule->table.name = name ? strdup(name) : NULL;
3088 LIST_INIT(&rule->list);
3089 if (flags & STK_ON_RSP)
3090 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3091 else
3092 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003095 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003097
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3099 curproxy->uri_auth = NULL; /* we must detach from the default config */
3100
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003101 if (!*args[1]) {
3102 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003103 } else if (!strcmp(args[1], "admin")) {
3104 struct stats_admin_rule *rule;
3105
3106 if (curproxy == &defproxy) {
3107 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
3110 }
3111
3112 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3113 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3114 err_code |= ERR_ALERT | ERR_ABORT;
3115 goto out;
3116 }
3117
3118 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3119 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3120 file, linenum, args[0], args[1]);
3121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
3123 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003124 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3125 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3126 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
3129 }
3130
3131 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3132
3133 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3134 rule->cond = cond;
3135 LIST_INIT(&rule->list);
3136 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 } else if (!strcmp(args[1], "uri")) {
3138 if (*(args[2]) == 0) {
3139 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3143 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003144 err_code |= ERR_ALERT | ERR_ABORT;
3145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 }
3147 } else if (!strcmp(args[1], "realm")) {
3148 if (*(args[2]) == 0) {
3149 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3153 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_ABORT;
3155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003157 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003158 unsigned interval;
3159
3160 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3161 if (err) {
3162 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3163 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003166 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3167 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003168 err_code |= ERR_ALERT | ERR_ABORT;
3169 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003170 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003171 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003172 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003173
3174 if (curproxy == &defproxy) {
3175 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
3178 }
3179
3180 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3181 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3182 err_code |= ERR_ALERT | ERR_ABORT;
3183 goto out;
3184 }
3185
Willy Tarreauff011f22011-01-06 17:51:27 +01003186 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3187 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003188 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3189 file, linenum, args[0]);
3190 err_code |= ERR_WARN;
3191 }
3192
Willy Tarreauff011f22011-01-06 17:51:27 +01003193 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003194
Willy Tarreauff011f22011-01-06 17:51:27 +01003195 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003196 err_code |= ERR_ALERT | ERR_ABORT;
3197 goto out;
3198 }
3199
Willy Tarreauff011f22011-01-06 17:51:27 +01003200 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3201 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003202
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 } else if (!strcmp(args[1], "auth")) {
3204 if (*(args[2]) == 0) {
3205 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3209 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003210 err_code |= ERR_ALERT | ERR_ABORT;
3211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003212 }
3213 } else if (!strcmp(args[1], "scope")) {
3214 if (*(args[2]) == 0) {
3215 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3219 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_ALERT | ERR_ABORT;
3221 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 }
3223 } else if (!strcmp(args[1], "enable")) {
3224 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3225 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003226 err_code |= ERR_ALERT | ERR_ABORT;
3227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003229 } else if (!strcmp(args[1], "hide-version")) {
3230 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3231 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_ABORT;
3233 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003234 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003235 } else if (!strcmp(args[1], "show-legends")) {
3236 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3237 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3238 err_code |= ERR_ALERT | ERR_ABORT;
3239 goto out;
3240 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003241 } else if (!strcmp(args[1], "show-node")) {
3242
3243 if (*args[2]) {
3244 int i;
3245 char c;
3246
3247 for (i=0; args[2][i]; i++) {
3248 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003249 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3250 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003251 break;
3252 }
3253
3254 if (!i || args[2][i]) {
3255 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3256 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3257 file, linenum, args[0], args[1]);
3258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
3260 }
3261 }
3262
3263 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3264 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
3268 } else if (!strcmp(args[1], "show-desc")) {
3269 char *desc = NULL;
3270
3271 if (*args[2]) {
3272 int i, len=0;
3273 char *d;
3274
3275 for(i=2; *args[i]; i++)
3276 len += strlen(args[i])+1;
3277
3278 desc = d = (char *)calloc(1, len);
3279
3280 d += sprintf(d, "%s", args[2]);
3281 for(i=3; *args[i]; i++)
3282 d += sprintf(d, " %s", args[i]);
3283 }
3284
3285 if (!*args[2] && !global.desc)
3286 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3287 file, linenum, args[1]);
3288 else {
3289 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3290 free(desc);
3291 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3292 err_code |= ERR_ALERT | ERR_ABORT;
3293 goto out;
3294 }
3295 free(desc);
3296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003298stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003299 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 +01003300 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 }
3304 }
3305 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003306 int optnum;
3307
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003308 if (*(args[1]) == '\0') {
3309 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3310 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003314
3315 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3316 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003317 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3318 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3319 file, linenum, cfg_opts[optnum].name);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322 }
Willy Tarreau93893792009-07-23 13:19:11 +02003323 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3324 err_code |= ERR_WARN;
3325 goto out;
3326 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003327
Willy Tarreau3842f002009-06-14 11:39:52 +02003328 curproxy->no_options &= ~cfg_opts[optnum].val;
3329 curproxy->options &= ~cfg_opts[optnum].val;
3330
3331 switch (kwm) {
3332 case KWM_STD:
3333 curproxy->options |= cfg_opts[optnum].val;
3334 break;
3335 case KWM_NO:
3336 curproxy->no_options |= cfg_opts[optnum].val;
3337 break;
3338 case KWM_DEF: /* already cleared */
3339 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003340 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003341
Willy Tarreau93893792009-07-23 13:19:11 +02003342 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003343 }
3344 }
3345
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003346 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3347 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003348 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3349 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3350 file, linenum, cfg_opts2[optnum].name);
3351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
3353 }
Willy Tarreau93893792009-07-23 13:19:11 +02003354 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3355 err_code |= ERR_WARN;
3356 goto out;
3357 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003358
Willy Tarreau3842f002009-06-14 11:39:52 +02003359 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3360 curproxy->options2 &= ~cfg_opts2[optnum].val;
3361
3362 switch (kwm) {
3363 case KWM_STD:
3364 curproxy->options2 |= cfg_opts2[optnum].val;
3365 break;
3366 case KWM_NO:
3367 curproxy->no_options2 |= cfg_opts2[optnum].val;
3368 break;
3369 case KWM_DEF: /* already cleared */
3370 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003371 }
Willy Tarreau93893792009-07-23 13:19:11 +02003372 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003373 }
3374 }
3375
Willy Tarreau3842f002009-06-14 11:39:52 +02003376 if (kwm != KWM_STD) {
3377 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003378 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003381 }
3382
Emeric Brun3a058f32009-06-30 18:26:00 +02003383 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003384 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003385 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003386 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003387 if (*(args[2]) != '\0') {
3388 if (!strcmp(args[2], "clf")) {
3389 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003390 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003391 } else {
3392 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003395 }
3396 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003397 if (curproxy->logformat_string != default_http_log_format &&
3398 curproxy->logformat_string != default_tcp_log_format &&
3399 curproxy->logformat_string != clf_http_log_format)
3400 free(curproxy->logformat_string);
3401 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003402 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003403 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003405 if (curproxy->logformat_string != default_http_log_format &&
3406 curproxy->logformat_string != default_tcp_log_format &&
3407 curproxy->logformat_string != clf_http_log_format)
3408 free(curproxy->logformat_string);
3409 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003410 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 else if (!strcmp(args[1], "tcpka")) {
3412 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003413 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003414 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003415
3416 if (curproxy->cap & PR_CAP_FE)
3417 curproxy->options |= PR_O_TCP_CLI_KA;
3418 if (curproxy->cap & PR_CAP_BE)
3419 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 }
3421 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003422 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003423 err_code |= ERR_WARN;
3424
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003426 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003427 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003428 curproxy->options2 &= ~PR_O2_CHK_ANY;
3429 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 if (!*args[2]) { /* no argument */
3431 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3432 curproxy->check_len = strlen(DEF_CHECK_REQ);
3433 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003434 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 curproxy->check_req = (char *)malloc(reqlen);
3436 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003437 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003439 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003440 if (*args[4])
3441 reqlen += strlen(args[4]);
3442 else
3443 reqlen += strlen("HTTP/1.0");
3444
3445 curproxy->check_req = (char *)malloc(reqlen);
3446 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003447 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003449 }
3450 else if (!strcmp(args[1], "ssl-hello-chk")) {
3451 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003452 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003453 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003454
Willy Tarreaua534fea2008-08-03 12:19:50 +02003455 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003456 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003457 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003458 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003459 }
Willy Tarreau23677902007-05-08 23:50:35 +02003460 else if (!strcmp(args[1], "smtpchk")) {
3461 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003462 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003463 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003464 curproxy->options2 &= ~PR_O2_CHK_ANY;
3465 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003466
3467 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3468 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3469 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3470 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3471 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3472 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3473 curproxy->check_req = (char *)malloc(reqlen);
3474 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3475 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3476 } else {
3477 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3478 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3479 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3480 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3481 }
3482 }
3483 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003484 else if (!strcmp(args[1], "pgsql-check")) {
3485 /* use PostgreSQL request to check servers' health */
3486 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3487 err_code |= ERR_WARN;
3488
3489 free(curproxy->check_req);
3490 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003491 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003492 curproxy->options2 |= PR_O2_PGSQL_CHK;
3493
3494 if (*(args[2])) {
3495 int cur_arg = 2;
3496
3497 while (*(args[cur_arg])) {
3498 if (strcmp(args[cur_arg], "user") == 0) {
3499 char * packet;
3500 uint32_t packet_len;
3501 uint32_t pv;
3502
3503 /* suboption header - needs additional argument for it */
3504 if (*(args[cur_arg+1]) == 0) {
3505 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3506 file, linenum, args[0], args[1], args[cur_arg]);
3507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
3509 }
3510
3511 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3512 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3513 pv = htonl(0x30000); /* protocol version 3.0 */
3514
3515 packet = (char*) calloc(1, packet_len);
3516
3517 memcpy(packet + 4, &pv, 4);
3518
3519 /* copy "user" */
3520 memcpy(packet + 8, "user", 4);
3521
3522 /* copy username */
3523 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3524
3525 free(curproxy->check_req);
3526 curproxy->check_req = packet;
3527 curproxy->check_len = packet_len;
3528
3529 packet_len = htonl(packet_len);
3530 memcpy(packet, &packet_len, 4);
3531 cur_arg += 2;
3532 } else {
3533 /* unknown suboption - catchall */
3534 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3535 file, linenum, args[0], args[1]);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 } /* end while loop */
3540 }
3541 }
3542
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003543 else if (!strcmp(args[1], "redis-check")) {
3544 /* use REDIS PING request to check servers' health */
3545 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3546 err_code |= ERR_WARN;
3547
3548 free(curproxy->check_req);
3549 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003550 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003551 curproxy->options2 |= PR_O2_REDIS_CHK;
3552
3553 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3554 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3555 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3556 }
3557
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003558 else if (!strcmp(args[1], "mysql-check")) {
3559 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003560 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3561 err_code |= ERR_WARN;
3562
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003563 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003564 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003565 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003566 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003567
3568 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3569 * const char mysql40_client_auth_pkt[] = {
3570 * "\x0e\x00\x00" // packet length
3571 * "\x01" // packet number
3572 * "\x00\x00" // client capabilities
3573 * "\x00\x00\x01" // max packet
3574 * "haproxy\x00" // username (null terminated string)
3575 * "\x00" // filler (always 0x00)
3576 * "\x01\x00\x00" // packet length
3577 * "\x00" // packet number
3578 * "\x01" // COM_QUIT command
3579 * };
3580 */
3581
3582 if (*(args[2])) {
3583 int cur_arg = 2;
3584
3585 while (*(args[cur_arg])) {
3586 if (strcmp(args[cur_arg], "user") == 0) {
3587 char *mysqluser;
3588 int packetlen, reqlen, userlen;
3589
3590 /* suboption header - needs additional argument for it */
3591 if (*(args[cur_arg+1]) == 0) {
3592 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3593 file, linenum, args[0], args[1], args[cur_arg]);
3594 err_code |= ERR_ALERT | ERR_FATAL;
3595 goto out;
3596 }
3597 mysqluser = args[cur_arg + 1];
3598 userlen = strlen(mysqluser);
3599 packetlen = userlen + 7;
3600 reqlen = packetlen + 9;
3601
3602 free(curproxy->check_req);
3603 curproxy->check_req = (char *)calloc(1, reqlen);
3604 curproxy->check_len = reqlen;
3605
3606 snprintf(curproxy->check_req, 4, "%c%c%c",
3607 ((unsigned char) packetlen & 0xff),
3608 ((unsigned char) (packetlen >> 8) & 0xff),
3609 ((unsigned char) (packetlen >> 16) & 0xff));
3610
3611 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003612 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003613 curproxy->check_req[8] = 1;
3614 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3615 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3616 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3617 cur_arg += 2;
3618 } else {
3619 /* unknown suboption - catchall */
3620 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3621 file, linenum, args[0], args[1]);
3622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
3624 }
3625 } /* end while loop */
3626 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003627 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003628 else if (!strcmp(args[1], "ldap-check")) {
3629 /* use LDAP request to check servers' health */
3630 free(curproxy->check_req);
3631 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003632 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003633 curproxy->options2 |= PR_O2_LDAP_CHK;
3634
3635 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3636 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3637 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3638 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003639 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003640 int cur_arg;
3641
3642 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3643 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003644 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003645
Willy Tarreau87cf5142011-08-19 22:57:24 +02003646 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003647
3648 free(curproxy->fwdfor_hdr_name);
3649 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3650 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3651
3652 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3653 cur_arg = 2;
3654 while (*(args[cur_arg])) {
3655 if (!strcmp(args[cur_arg], "except")) {
3656 /* suboption except - needs additional argument for it */
3657 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3658 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3659 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003662 }
3663 /* flush useless bits */
3664 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003665 cur_arg += 2;
3666 } else if (!strcmp(args[cur_arg], "header")) {
3667 /* suboption header - needs additional argument for it */
3668 if (*(args[cur_arg+1]) == 0) {
3669 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3670 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_ALERT | ERR_FATAL;
3672 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003673 }
3674 free(curproxy->fwdfor_hdr_name);
3675 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3676 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3677 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003678 } else if (!strcmp(args[cur_arg], "if-none")) {
3679 curproxy->options &= ~PR_O_FF_ALWAYS;
3680 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003681 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003682 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003683 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003684 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003685 err_code |= ERR_ALERT | ERR_FATAL;
3686 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003687 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003688 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003689 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003690 else if (!strcmp(args[1], "originalto")) {
3691 int cur_arg;
3692
3693 /* insert x-original-to field, but not for the IP address listed as an except.
3694 * set default options (ie: bitfield, header name, etc)
3695 */
3696
3697 curproxy->options |= PR_O_ORGTO;
3698
3699 free(curproxy->orgto_hdr_name);
3700 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3701 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3702
Willy Tarreau87cf5142011-08-19 22:57:24 +02003703 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003704 cur_arg = 2;
3705 while (*(args[cur_arg])) {
3706 if (!strcmp(args[cur_arg], "except")) {
3707 /* suboption except - needs additional argument for it */
3708 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3709 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3710 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_ALERT | ERR_FATAL;
3712 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003713 }
3714 /* flush useless bits */
3715 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3716 cur_arg += 2;
3717 } else if (!strcmp(args[cur_arg], "header")) {
3718 /* suboption header - needs additional argument for it */
3719 if (*(args[cur_arg+1]) == 0) {
3720 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3721 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003724 }
3725 free(curproxy->orgto_hdr_name);
3726 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3727 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3728 cur_arg += 2;
3729 } else {
3730 /* unknown suboption - catchall */
3731 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3732 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003735 }
3736 } /* end while loop */
3737 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 else {
3739 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003742 }
Willy Tarreau93893792009-07-23 13:19:11 +02003743 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003744 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003745 else if (!strcmp(args[0], "default_backend")) {
3746 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003747 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003748
3749 if (*(args[1]) == 0) {
3750 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003753 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003754 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003755 curproxy->defbe.name = strdup(args[1]);
3756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003757 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003758 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003759 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003760
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003761 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3762 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 /* enable reconnections to dispatch */
3765 curproxy->options |= PR_O_REDISP;
3766 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003767 else if (!strcmp(args[0], "http-check")) {
3768 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003769 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003770
3771 if (strcmp(args[1], "disable-on-404") == 0) {
3772 /* enable a graceful server shutdown on an HTTP 404 response */
3773 curproxy->options |= PR_O_DISABLE404;
3774 }
Willy Tarreauef781042010-01-27 11:53:01 +01003775 else if (strcmp(args[1], "send-state") == 0) {
3776 /* enable emission of the apparent state of a server in HTTP checks */
3777 curproxy->options2 |= PR_O2_CHK_SNDST;
3778 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003779 else if (strcmp(args[1], "expect") == 0) {
3780 const char *ptr_arg;
3781 int cur_arg;
3782
3783 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3784 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3785 err_code |= ERR_ALERT | ERR_FATAL;
3786 goto out;
3787 }
3788
3789 cur_arg = 2;
3790 /* consider exclamation marks, sole or at the beginning of a word */
3791 while (*(ptr_arg = args[cur_arg])) {
3792 while (*ptr_arg == '!') {
3793 curproxy->options2 ^= PR_O2_EXP_INV;
3794 ptr_arg++;
3795 }
3796 if (*ptr_arg)
3797 break;
3798 cur_arg++;
3799 }
3800 /* now ptr_arg points to the beginning of a word past any possible
3801 * exclamation mark, and cur_arg is the argument which holds this word.
3802 */
3803 if (strcmp(ptr_arg, "status") == 0) {
3804 if (!*(args[cur_arg + 1])) {
3805 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3806 file, linenum, args[0], args[1], ptr_arg);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
3810 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003811 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003812 curproxy->expect_str = strdup(args[cur_arg + 1]);
3813 }
3814 else if (strcmp(ptr_arg, "string") == 0) {
3815 if (!*(args[cur_arg + 1])) {
3816 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3817 file, linenum, args[0], args[1], ptr_arg);
3818 err_code |= ERR_ALERT | ERR_FATAL;
3819 goto out;
3820 }
3821 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003822 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003823 curproxy->expect_str = strdup(args[cur_arg + 1]);
3824 }
3825 else if (strcmp(ptr_arg, "rstatus") == 0) {
3826 if (!*(args[cur_arg + 1])) {
3827 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3828 file, linenum, args[0], args[1], ptr_arg);
3829 err_code |= ERR_ALERT | ERR_FATAL;
3830 goto out;
3831 }
3832 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003833 free(curproxy->expect_str);
3834 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3835 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003836 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3837 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3838 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3839 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 }
3844 else if (strcmp(ptr_arg, "rstring") == 0) {
3845 if (!*(args[cur_arg + 1])) {
3846 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3847 file, linenum, args[0], args[1], ptr_arg);
3848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
3850 }
3851 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003852 free(curproxy->expect_str);
3853 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3854 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003855 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3856 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3857 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3858 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
3861 }
3862 }
3863 else {
3864 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3865 file, linenum, args[0], args[1], ptr_arg);
3866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
3869 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003870 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003871 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 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003874 }
3875 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003876 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003877 if (curproxy == &defproxy) {
3878 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003881 }
3882
Willy Tarreaub80c2302007-11-30 20:51:32 +01003883 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003884 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003885
3886 if (strcmp(args[1], "fail") == 0) {
3887 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003888 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003889 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3890 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003893 }
3894
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003895 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3896 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3897 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003900 }
3901 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3902 }
3903 else {
3904 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003907 }
3908 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909#ifdef TPROXY
3910 else if (!strcmp(args[0], "transparent")) {
3911 /* enable transparent proxy connections */
3912 curproxy->options |= PR_O_TRANSP;
3913 }
3914#endif
3915 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003916 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003918
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 if (*(args[1]) == 0) {
3920 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003923 }
3924 curproxy->maxconn = atol(args[1]);
3925 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003926 else if (!strcmp(args[0], "backlog")) { /* backlog */
3927 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003929
3930 if (*(args[1]) == 0) {
3931 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_ALERT | ERR_FATAL;
3933 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003934 }
3935 curproxy->backlog = atol(args[1]);
3936 }
Willy Tarreau86034312006-12-29 00:10:33 +01003937 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003938 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003940
Willy Tarreau86034312006-12-29 00:10:33 +01003941 if (*(args[1]) == 0) {
3942 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003945 }
3946 curproxy->fullconn = atol(args[1]);
3947 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3949 if (*(args[1]) == 0) {
3950 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003953 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003954 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3955 if (err) {
3956 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3957 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003960 }
3961 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003962 }
3963 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003964 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003965 if (curproxy == &defproxy) {
3966 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003970 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003972
Willy Tarreaubaaee002006-06-26 02:48:02 +02003973 if (strchr(args[1], ':') == NULL) {
3974 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_ALERT | ERR_FATAL;
3976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003977 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003978 sk = str2sa(args[1]);
3979 if (!sk) {
3980 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3981 err_code |= ERR_ALERT | ERR_FATAL;
3982 goto out;
3983 }
3984 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003985 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003986 }
3987 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003988 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003990
Willy Tarreaua93c74b2012-05-08 18:14:39 +02003991 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
3992 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003997 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3998 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3999 err_code |= ERR_WARN;
4000
4001 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4002 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4003 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4004 }
4005 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4006 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4007 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4008 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004009 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4010 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4011 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4012 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004013 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004014 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004019 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004020 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004021 char *rport, *raddr;
4022 short realport = 0;
4023 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004025 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_ALERT | ERR_FATAL;
4028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004029 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004030 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032
4033 if (!*args[2]) {
4034 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4035 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004039
4040 err = invalid_char(args[1]);
4041 if (err) {
4042 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4043 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004044 err_code |= ERR_ALERT | ERR_FATAL;
4045 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004046 }
4047
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004048 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004049 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004050
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004051 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4052 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4053 err_code |= ERR_ALERT | ERR_ABORT;
4054 goto out;
4055 }
4056
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004057 /* the servers are linked backwards first */
4058 newsrv->next = curproxy->srv;
4059 curproxy->srv = newsrv;
4060 newsrv->proxy = curproxy;
4061 newsrv->conf.file = file;
4062 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004063
Simon Hormanaf514952011-06-21 14:34:57 +09004064 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004065 LIST_INIT(&newsrv->pendconns);
4066 do_check = 0;
4067 newsrv->state = SRV_RUNNING; /* early server setup */
4068 newsrv->last_change = now.tv_sec;
4069 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004071 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004072 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004073 * - IP: => port=+0, relative
4074 * - IP:N => port=N, absolute
4075 * - IP:+N => port=+N, relative
4076 * - IP:-N => port=-N, relative
4077 */
4078 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004079 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004080 if (rport) {
4081 *rport++ = 0;
4082 realport = atol(rport);
4083 if (!isdigit((unsigned char)*rport))
4084 newsrv->state |= SRV_MAPPORTS;
4085 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004087
Willy Tarreaufab5a432011-03-04 15:31:53 +01004088 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004089 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004090 if (!sk) {
4091 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095 newsrv->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004096 newsrv->proto = protocol_by_family(newsrv->addr.ss_family);
Willy Tarreauc5788912012-08-24 18:12:41 +02004097 newsrv->data = &raw_sock;
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 */