blob: 10fc4a644bd353189688d17b17ccbfe11159d5b4 [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 Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.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>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
135 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
137 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
138 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
139 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
140 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
141 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100142#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100144#else
145 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100146#endif
147
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149};
150
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100151/* proxy->options2 */
152static const struct cfg_opt cfg_opts2[] =
153{
154#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
156 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100158#else
159 { "splice-request", 0, 0, 0, 0 },
160 { "splice-response", 0, 0, 0, 0 },
161 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100162#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
164 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
165 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
166 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
167 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
168 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
169 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
171 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400172 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200174 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200175 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176 { NULL, 0, 0, 0 }
177};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178
Willy Tarreau6daf3432008-01-22 16:44:08 +0100179static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
181int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100182int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200184/* List head of all known configuration keywords */
185static struct cfg_kw_list cfg_keywords = {
186 .list = LIST_HEAD_INIT(cfg_keywords.list)
187};
188
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189/*
190 * converts <str> to a list of listeners which are dynamically allocated.
191 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
192 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
193 * - <port> is a numerical port from 1 to 65535 ;
194 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
195 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200196 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
197 * not NULL, it must be a valid pointer to either NULL or a freeable area that
198 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200200int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201{
202 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100203 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 int port, end;
205
206 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 while (next && *next) {
209 struct sockaddr_storage ss;
210
211 str = next;
212 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100213 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214 *next++ = 0;
215 }
216
Emeric Bruned760922010-10-22 17:59:25 +0200217 if (*str == '/') {
218 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
219 /* so compute max path */
220 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
221 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 +0200222
Emeric Bruned760922010-10-22 17:59:25 +0200223 if (strlen(str) > max_path_len) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200224 memprintf(err, "socket path '%s' too long (max %d)\n", str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200225 goto fail;
226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200229 ss.ss_family = AF_UNIX;
230 if (global.unix_bind.prefix) {
231 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
232 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 }
Emeric Bruned760922010-10-22 17:59:25 +0200234 else {
235 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
236 }
237 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 }
239 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100240 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100242 ss2 = str2sa_range(str, &port, &end);
243 if (!ss2) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "invalid listening address: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 if (!port) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200249 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100250 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100253 /* OK the address looks correct */
254 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
266
267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100269 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200270 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
271 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
272 l->frontend = curproxy;
273 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
275 l->fd = -1;
276 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200277 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 l->state = LI_INIT;
279
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100280 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 tcpv4_add_listener(l);
283 }
Emeric Bruned760922010-10-22 17:59:25 +0200284 else if (ss.ss_family == AF_INET6) {
285 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
286 tcpv6_add_listener(l);
287 }
288 else {
Emeric Bruned760922010-10-22 17:59:25 +0200289 uxst_add_listener(l);
290 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200292 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 } /* end for(port) */
295 } /* end while(next) */
296 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200297 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 fail:
299 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301}
302
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303/*
304 * Sends a warning if proxy <proxy> does not have at least one of the
305 * capabilities in <cap>. An optionnal <hint> may be added at the end
306 * of the warning to help the user. Returns 1 if a warning was emitted
307 * or 0 if the condition is valid.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100310{
311 char *msg;
312
313 switch (cap) {
314 case PR_CAP_BE: msg = "no backend"; break;
315 case PR_CAP_FE: msg = "no frontend"; break;
316 case PR_CAP_RS: msg = "no ruleset"; break;
317 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
318 default: msg = "not enough"; break;
319 }
320
321 if (!(proxy->cap & cap)) {
322 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100323 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100324 return 1;
325 }
326 return 0;
327}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328
Willy Tarreau61d18892009-03-31 10:49:21 +0200329/* Report a warning if a rule is placed after a 'block' rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
334 if (!LIST_ISEMPTY(&proxy->block_cond)) {
335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a reqrewrite rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (proxy->req_exp) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a reqadd rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100360 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* Report a warning if a rule is placed after a redirect rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
381/* Report a warning if a rule is placed after a 'use_backend' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
394/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
398 warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418/* Report it if a request ACL condition uses some response-only parameters. It
419 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
420 * Note that <cond> may be NULL and then will be ignored.
421 */
422static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
423{
424 struct acl *acl;
425
426 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
427 return 0;
428
429 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
430 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
431 file, line, acl ? acl->name : "(unknown)");
432 return ERR_WARN;
433}
434
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100435/* Report it if a request ACL condition uses some request-only volatile parameters.
436 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
437 * Note that <cond> may be NULL and then will be ignored.
438 */
439static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
440{
441 struct acl *acl;
442
443 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
444 return 0;
445
446 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
447 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
448 file, line, acl ? acl->name : "(unknown)");
449 return ERR_WARN;
450}
451
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100452
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 * parse a line in a <global> section. Returns the error code, 0 if OK, or
455 * any combination of :
456 * - ERR_ABORT: must abort ASAP
457 * - ERR_FATAL: we can continue parsing but not start the service
458 * - ERR_WARN: a warning has been emitted
459 * - ERR_ALERT: an alert has been emitted
460 * Only the two first ones can stop processing, the two others are just
461 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200463int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464{
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200466 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (!strcmp(args[0], "global")) { /* new section */
469 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200472 else if (!strcmp(args[0], "ca-base")) {
473#ifdef USE_OPENSSL
474 if (global.ca_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.ca_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
491 else if (!strcmp(args[0], "crt-base")) {
492#ifdef USE_OPENSSL
493 if (global.crt_base != NULL) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.crt_base = strdup(args[1]);
504#else
505 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
508#endif
509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "daemon")) {
511 global.mode |= MODE_DAEMON;
512 }
513 else if (!strcmp(args[0], "debug")) {
514 global.mode |= MODE_DEBUG;
515 }
516 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100517 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100520 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100523 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100525 else if (!strcmp(args[0], "nosplice")) {
526 global.tune.options &= ~GTUNE_USE_SPLICE;
527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 else if (!strcmp(args[0], "quiet")) {
529 global.mode |= MODE_QUIET;
530 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200531 else if (!strcmp(args[0], "tune.maxpollevents")) {
532 if (global.tune.maxpollevents != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200541 }
542 global.tune.maxpollevents = atol(args[1]);
543 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100544 else if (!strcmp(args[0], "tune.maxaccept")) {
545 if (global.tune.maxaccept != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100554 }
555 global.tune.maxaccept = atol(args[1]);
556 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200557 else if (!strcmp(args[0], "tune.chksize")) {
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.chksize = atol(args[1]);
564 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200565#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100566 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.sslcachesize = atol(args[1]);
573 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100574 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
575 unsigned int ssllifetime;
576 const char *res;
577
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583
584 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
585 if (res) {
586 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
587 file, linenum, *res, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591
592 global.tune.ssllifetime = ssllifetime;
593 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200594#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200595 else if (!strcmp(args[0], "tune.bufsize")) {
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.tune.bufsize = atol(args[1]);
602 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
603 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100604 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200605 }
606 else if (!strcmp(args[0], "tune.maxrewrite")) {
607 if (*(args[1]) == 0) {
608 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
609 err_code |= ERR_ALERT | ERR_FATAL;
610 goto out;
611 }
612 global.tune.maxrewrite = atol(args[1]);
613 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
614 global.tune.maxrewrite = global.tune.bufsize / 2;
615 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100616 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
617 if (global.tune.client_rcvbuf != 0) {
618 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT;
620 goto out;
621 }
622 if (*(args[1]) == 0) {
623 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626 }
627 global.tune.client_rcvbuf = atol(args[1]);
628 }
629 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
630 if (global.tune.server_rcvbuf != 0) {
631 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
632 err_code |= ERR_ALERT;
633 goto out;
634 }
635 if (*(args[1]) == 0) {
636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT | ERR_FATAL;
638 goto out;
639 }
640 global.tune.server_rcvbuf = atol(args[1]);
641 }
642 else if (!strcmp(args[0], "tune.sndbuf.client")) {
643 if (global.tune.client_sndbuf != 0) {
644 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
645 err_code |= ERR_ALERT;
646 goto out;
647 }
648 if (*(args[1]) == 0) {
649 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT | ERR_FATAL;
651 goto out;
652 }
653 global.tune.client_sndbuf = atol(args[1]);
654 }
655 else if (!strcmp(args[0], "tune.sndbuf.server")) {
656 if (global.tune.server_sndbuf != 0) {
657 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
658 err_code |= ERR_ALERT;
659 goto out;
660 }
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666 global.tune.server_sndbuf = atol(args[1]);
667 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200668 else if (!strcmp(args[0], "tune.pipesize")) {
669 if (*(args[1]) == 0) {
670 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674 global.tune.pipesize = atol(args[1]);
675 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200676 else if (!strcmp(args[0], "tune.http.maxhdr")) {
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
681 }
682 global.tune.max_http_hdr = atol(args[1]);
683 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100684 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
685#ifdef USE_ZLIB
686 if (*args[1]) {
687 global.tune.zlibmemlevel = atoi(args[1]);
688 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
689 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
690 file, linenum, args[0]);
691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
693 }
694 } else {
695 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
696 file, linenum, args[0]);
697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
699 }
700#else
701 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704#endif
705 }
706 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
707#ifdef USE_ZLIB
708 if (*args[1]) {
709 global.tune.zlibwindowsize = atoi(args[1]);
710 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
711 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
712 file, linenum, args[0]);
713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
715 }
716 } else {
717 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
718 file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722#else
723 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
726#endif
727 }
William Lallemandf3747832012-11-09 12:33:10 +0100728 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
729 if (*args[1]) {
730 global.tune.comp_maxlevel = atoi(args[1]);
731 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
732 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
733 file, linenum, args[0]);
734 err_code |= ERR_ALERT | ERR_FATAL;
735 goto out;
736 }
737 } else {
738 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
739 file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200744 else if (!strcmp(args[0], "uid")) {
745 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200746 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200747 err_code |= ERR_ALERT;
748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200749 }
750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200754 }
755 global.uid = atol(args[1]);
756 }
757 else if (!strcmp(args[0], "gid")) {
758 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200759 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 }
768 global.gid = atol(args[1]);
769 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200770 /* user/group name handling */
771 else if (!strcmp(args[0], "user")) {
772 struct passwd *ha_user;
773 if (global.uid != 0) {
774 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200775 err_code |= ERR_ALERT;
776 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200777 }
778 errno = 0;
779 ha_user = getpwnam(args[1]);
780 if (ha_user != NULL) {
781 global.uid = (int)ha_user->pw_uid;
782 }
783 else {
784 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 +0200785 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200786 }
787 }
788 else if (!strcmp(args[0], "group")) {
789 struct group *ha_group;
790 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200791 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT;
793 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200794 }
795 errno = 0;
796 ha_group = getgrnam(args[1]);
797 if (ha_group != NULL) {
798 global.gid = (int)ha_group->gr_gid;
799 }
800 else {
801 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 +0200802 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200803 }
804 }
805 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200806 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200811 }
812 global.nbproc = atol(args[1]);
813 }
814 else if (!strcmp(args[0], "maxconn")) {
815 if (global.maxconn != 0) {
816 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200817 err_code |= ERR_ALERT;
818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 }
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 }
825 global.maxconn = atol(args[1]);
826#ifdef SYSTEM_MAXCONN
827 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
828 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);
829 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200831 }
832#endif /* SYSTEM_MAXCONN */
833 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200834 else if (!strcmp(args[0], "maxsslconn")) {
835#ifdef USE_OPENSSL
836 if (*(args[1]) == 0) {
837 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
838 err_code |= ERR_ALERT | ERR_FATAL;
839 goto out;
840 }
841 global.maxsslconn = atol(args[1]);
842#else
Emeric Brun0914df82012-10-02 18:45:42 +0200843 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200846#endif
847 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200848 else if (!strcmp(args[0], "maxconnrate")) {
849 if (global.cps_lim != 0) {
850 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT;
852 goto out;
853 }
854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 global.cps_lim = atol(args[1]);
860 }
William Lallemandd85f9172012-11-09 17:05:39 +0100861 else if (!strcmp(args[0], "maxcomprate")) {
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 global.comp_rate_lim = atoi(args[1]) * 1024;
868 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100869 else if (!strcmp(args[0], "maxpipes")) {
870 if (global.maxpipes != 0) {
871 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200872 err_code |= ERR_ALERT;
873 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100874 }
875 if (*(args[1]) == 0) {
876 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100879 }
880 global.maxpipes = atol(args[1]);
881 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100882 else if (!strcmp(args[0], "maxzlibmem")) {
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888 global.maxzlibmem = atol(args[1]);
889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890 else if (!strcmp(args[0], "ulimit-n")) {
891 if (global.rlimit_nofile != 0) {
892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200893 err_code |= ERR_ALERT;
894 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895 }
896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 global.rlimit_nofile = atol(args[1]);
902 }
903 else if (!strcmp(args[0], "chroot")) {
904 if (global.chroot != NULL) {
905 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200906 err_code |= ERR_ALERT;
907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 }
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 }
914 global.chroot = strdup(args[1]);
915 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200916 else if (!strcmp(args[0], "description")) {
917 int i, len=0;
918 char *d;
919
920 if (!*args[1]) {
921 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
922 file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926
927 for(i=1; *args[i]; i++)
928 len += strlen(args[i])+1;
929
930 if (global.desc)
931 free(global.desc);
932
933 global.desc = d = (char *)calloc(1, len);
934
935 d += sprintf(d, "%s", args[1]);
936 for(i=2; *args[i]; i++)
937 d += sprintf(d, " %s", args[i]);
938 }
939 else if (!strcmp(args[0], "node")) {
940 int i;
941 char c;
942
943 for (i=0; args[1][i]; i++) {
944 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100945 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
946 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200947 break;
948 }
949
950 if (!i || args[1][i]) {
951 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
952 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
953 file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957
958 if (global.node)
959 free(global.node);
960
961 global.node = strdup(args[1]);
962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 else if (!strcmp(args[0], "pidfile")) {
964 if (global.pidfile != NULL) {
965 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 global.pidfile = strdup(args[1]);
975 }
Emeric Bruned760922010-10-22 17:59:25 +0200976 else if (!strcmp(args[0], "unix-bind")) {
977 int cur_arg = 1;
978 while (*(args[cur_arg])) {
979 if (!strcmp(args[cur_arg], "prefix")) {
980 if (global.unix_bind.prefix != NULL) {
981 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
982 err_code |= ERR_ALERT;
983 cur_arg += 2;
984 continue;
985 }
986
987 if (*(args[cur_arg+1]) == 0) {
988 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
991 }
992 global.unix_bind.prefix = strdup(args[cur_arg+1]);
993 cur_arg += 2;
994 continue;
995 }
996
997 if (!strcmp(args[cur_arg], "mode")) {
998
999 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1000 cur_arg += 2;
1001 continue;
1002 }
1003
1004 if (!strcmp(args[cur_arg], "uid")) {
1005
1006 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1007 cur_arg += 2;
1008 continue;
1009 }
1010
1011 if (!strcmp(args[cur_arg], "gid")) {
1012
1013 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1014 cur_arg += 2;
1015 continue;
1016 }
1017
1018 if (!strcmp(args[cur_arg], "user")) {
1019 struct passwd *user;
1020
1021 user = getpwnam(args[cur_arg + 1]);
1022 if (!user) {
1023 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1024 file, linenum, args[0], args[cur_arg + 1 ]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028
1029 global.unix_bind.ux.uid = user->pw_uid;
1030 cur_arg += 2;
1031 continue;
1032 }
1033
1034 if (!strcmp(args[cur_arg], "group")) {
1035 struct group *group;
1036
1037 group = getgrnam(args[cur_arg + 1]);
1038 if (!group) {
1039 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1040 file, linenum, args[0], args[cur_arg + 1 ]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044
1045 global.unix_bind.ux.gid = group->gr_gid;
1046 cur_arg += 2;
1047 continue;
1048 }
1049
Willy Tarreaub48f9582011-09-05 01:17:06 +02001050 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001051 file, linenum, args[0]);
1052 err_code |= ERR_ALERT | ERR_FATAL;
1053 goto out;
1054 }
1055 }
William Lallemand0f99e342011-10-12 17:50:54 +02001056 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1057 /* delete previous herited or defined syslog servers */
1058 struct logsrv *back;
1059 struct logsrv *tmp;
1060
1061 if (*(args[1]) != 0) {
1062 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066
1067 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1068 LIST_DEL(&tmp->list);
1069 free(tmp);
1070 }
1071 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02001073 struct logsrv *logsrv;
1074
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075 if (*(args[1]) == 0 || *(args[2]) == 0) {
1076 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001077 err_code |= ERR_ALERT | ERR_FATAL;
1078 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079 }
William Lallemand0f99e342011-10-12 17:50:54 +02001080
1081 logsrv = calloc(1, sizeof(struct logsrv));
1082
1083 logsrv->facility = get_log_facility(args[2]);
1084 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001085 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001086 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001087 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 }
1089
William Lallemand0f99e342011-10-12 17:50:54 +02001090 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001092 logsrv->level = get_log_level(args[3]);
1093 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001094 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001096 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
1098 }
1099
William Lallemand0f99e342011-10-12 17:50:54 +02001100 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001101 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001102 logsrv->minlvl = get_log_level(args[4]);
1103 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001104 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001105 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001106 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001107 }
1108 }
1109
Robert Tsai81ae1952007-12-05 10:47:29 +01001110 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01001111 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001112 if (!sk) {
1113 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01001114 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001115 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001116 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001117 goto out;
1118 }
William Lallemand0f99e342011-10-12 17:50:54 +02001119 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01001120 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01001121 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01001122 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01001123 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
1124 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001125 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001126 goto out;
1127 }
William Lallemand0f99e342011-10-12 17:50:54 +02001128 logsrv->addr = *sk;
1129 if (!get_host_port(&logsrv->addr))
1130 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001132
William Lallemand0f99e342011-10-12 17:50:54 +02001133 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001134 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001135 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1136 char *name;
1137 int len;
1138
1139 if (global.log_send_hostname != NULL) {
1140 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1141 err_code |= ERR_ALERT;
1142 goto out;
1143 }
1144
1145 if (*(args[1]))
1146 name = args[1];
1147 else
1148 name = hostname;
1149
1150 len = strlen(name);
1151
1152 /* We'll add a space after the name to respect the log format */
1153 free(global.log_send_hostname);
1154 global.log_send_hostname = malloc(len + 2);
1155 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1156 }
Kevinm48936af2010-12-22 16:08:21 +00001157 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1158 if (*(args[1]) == 0) {
1159 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1160 err_code |= ERR_ALERT | ERR_FATAL;
1161 goto out;
1162 }
1163 free(global.log_tag);
1164 global.log_tag = strdup(args[1]);
1165 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001166 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1167 if (global.spread_checks != 0) {
1168 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001169 err_code |= ERR_ALERT;
1170 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001171 }
1172 if (*(args[1]) == 0) {
1173 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001174 err_code |= ERR_ALERT | ERR_FATAL;
1175 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001176 }
1177 global.spread_checks = atol(args[1]);
1178 if (global.spread_checks < 0 || global.spread_checks > 50) {
1179 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001180 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001182 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001183 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1184#ifdef USE_CPU_AFFINITY
1185 int cur_arg, i;
1186 unsigned int proc = 0;
1187 unsigned long cpus = 0;
1188
1189 if (strcmp(args[1], "all") == 0)
1190 proc = 0xFFFFFFFF;
1191 else if (strcmp(args[1], "odd") == 0)
1192 proc = 0x55555555;
1193 else if (strcmp(args[1], "even") == 0)
1194 proc = 0xAAAAAAAA;
1195 else {
1196 proc = atoi(args[1]);
1197 if (proc >= 1 && proc <= 32)
1198 proc = 1 << (proc - 1);
1199 }
1200
1201 if (!proc || !*args[2]) {
1202 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1203 file, linenum, args[0]);
1204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
1206 }
1207
1208 cur_arg = 2;
1209 while (*args[cur_arg]) {
1210 unsigned int low, high;
1211
1212 if (isdigit(*args[cur_arg])) {
1213 char *dash = strchr(args[cur_arg], '-');
1214
1215 low = high = str2uic(args[cur_arg]);
1216 if (dash)
1217 high = str2uic(dash + 1);
1218
1219 if (high < low) {
1220 unsigned int swap = low;
1221 low = high;
1222 high = swap;
1223 }
1224
1225 if (low < 0 || high >= sizeof(long) * 8) {
1226 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1227 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1228 err_code |= ERR_ALERT | ERR_FATAL;
1229 goto out;
1230 }
1231
1232 while (low <= high)
1233 cpus |= 1UL << low++;
1234 }
1235 else {
1236 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1237 file, linenum, args[0], args[cur_arg]);
1238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
1240 }
1241 cur_arg++;
1242 }
1243 for (i = 0; i < 32; i++)
1244 if (proc & (1 << i))
1245 global.cpu_map[i] = cpus;
1246#else
1247 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250#endif
1251 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001252 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001253 struct cfg_kw_list *kwl;
1254 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001255 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001256
1257 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1258 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1259 if (kwl->kw[index].section != CFG_GLOBAL)
1260 continue;
1261 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001262 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001263 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001264 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001265 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001266 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001267 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001268 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001269 err_code |= ERR_WARN;
1270 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001271 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001272 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001273 }
1274 }
1275 }
1276
Willy Tarreaubaaee002006-06-26 02:48:02 +02001277 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001278 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001279 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001280
Willy Tarreau058e9072009-07-20 09:30:05 +02001281 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001282 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001283 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001284}
1285
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001286void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001287{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001288 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001289 defproxy.mode = PR_MODE_TCP;
1290 defproxy.state = PR_STNEW;
1291 defproxy.maxconn = cfg_maxpconn;
1292 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001293
1294 defproxy.defsrv.inter = DEF_CHKINTR;
1295 defproxy.defsrv.fastinter = 0;
1296 defproxy.defsrv.downinter = 0;
1297 defproxy.defsrv.rise = DEF_RISETIME;
1298 defproxy.defsrv.fall = DEF_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001299 defproxy.defsrv.check.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001300 defproxy.defsrv.maxqueue = 0;
1301 defproxy.defsrv.minconn = 0;
1302 defproxy.defsrv.maxconn = 0;
1303 defproxy.defsrv.slowstart = 0;
1304 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1305 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1306 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001307}
1308
Willy Tarreauade5ec42010-01-28 19:33:49 +01001309
1310static int create_cond_regex_rule(const char *file, int line,
1311 struct proxy *px, int dir, int action, int flags,
1312 const char *cmd, const char *reg, const char *repl,
1313 const char **cond_start)
1314{
1315 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001316 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001317 const char *err;
1318 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001319 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001320
1321 if (px == &defproxy) {
1322 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto err;
1325 }
1326
1327 if (*reg == 0) {
1328 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1329 err_code |= ERR_ALERT | ERR_FATAL;
1330 goto err;
1331 }
1332
1333 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1334 err_code |= ERR_WARN;
1335
Willy Tarreau5321c422010-01-28 20:35:13 +01001336 if (cond_start &&
1337 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001338 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1339 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1340 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto err;
1343 }
1344 }
1345 else if (cond_start && **cond_start) {
1346 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1347 file, line, cmd, *cond_start);
1348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto err;
1350 }
1351
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001352 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001353 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001354 else
1355 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001356
Willy Tarreauade5ec42010-01-28 19:33:49 +01001357 preg = calloc(1, sizeof(regex_t));
1358 if (!preg) {
1359 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1360 err_code = ERR_ALERT | ERR_FATAL;
1361 goto err;
1362 }
1363
1364 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1365 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1366 err_code = ERR_ALERT | ERR_FATAL;
1367 goto err;
1368 }
1369
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001370 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001371 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001372 if (repl && err) {
1373 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1374 file, line, cmd, *err);
1375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto err;
1377 }
1378
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001379 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001380 err_code |= ERR_WARN;
1381
Willy Tarreauf4068b62012-05-08 17:37:49 +02001382 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001383 return err_code;
1384 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001385 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001386 free(preg);
1387 return err_code;
1388}
1389
Willy Tarreaubaaee002006-06-26 02:48:02 +02001390/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001391 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001392 * Returns the error code, 0 if OK, or any combination of :
1393 * - ERR_ABORT: must abort ASAP
1394 * - ERR_FATAL: we can continue parsing but not start the service
1395 * - ERR_WARN: a warning has been emitted
1396 * - ERR_ALERT: an alert has been emitted
1397 * Only the two first ones can stop processing, the two others are just
1398 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001399 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001400int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1401{
1402 static struct peers *curpeers = NULL;
1403 struct peer *newpeer = NULL;
1404 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001405 struct bind_conf *bind_conf;
1406 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001407 int err_code = 0;
1408
1409 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1410
1411 err = invalid_char(args[1]);
1412 if (err) {
1413 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1414 file, linenum, *err, args[0], args[1]);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 }
1417
1418 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1419 /*
1420 * If there are two proxies with the same name only following
1421 * combinations are allowed:
1422 */
1423 if (strcmp(curpeers->id, args[1]) == 0) {
1424 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1425 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1426 err_code |= ERR_WARN;
1427 }
1428 }
1429
1430 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1431 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1432 err_code |= ERR_ALERT | ERR_ABORT;
1433 goto out;
1434 }
1435
1436 curpeers->next = peers;
1437 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001438 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001439 curpeers->conf.line = linenum;
1440 curpeers->last_change = now.tv_sec;
1441 curpeers->id = strdup(args[1]);
1442 }
1443 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1444 char *rport, *raddr;
1445 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001446 struct sockaddr_storage *sk;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001447 char *err_msg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001448
1449 if (!*args[2]) {
1450 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1451 file, linenum, args[0]);
1452 err_code |= ERR_ALERT | ERR_FATAL;
1453 goto out;
1454 }
1455
1456 err = invalid_char(args[1]);
1457 if (err) {
1458 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1459 file, linenum, *err, args[1]);
1460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
1462 }
1463
1464 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1465 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1466 err_code |= ERR_ALERT | ERR_ABORT;
1467 goto out;
1468 }
1469
1470 /* the peers are linked backwards first */
1471 curpeers->count++;
1472 newpeer->next = curpeers->remote;
1473 curpeers->remote = newpeer;
1474 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001475 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001476 newpeer->conf.line = linenum;
1477
1478 newpeer->last_change = now.tv_sec;
1479 newpeer->id = strdup(args[1]);
1480
1481 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001482 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001483 if (rport) {
1484 *rport++ = 0;
1485 realport = atol(rport);
1486 }
1487 if (!realport) {
1488 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1489 err_code |= ERR_ALERT | ERR_FATAL;
1490 goto out;
1491 }
1492
Willy Tarreaufab5a432011-03-04 15:31:53 +01001493 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001494 free(raddr);
1495 if (!sk) {
1496 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1497 err_code |= ERR_ALERT | ERR_FATAL;
1498 goto out;
1499 }
1500 newpeer->addr = *sk;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001501 newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001502 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001503 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001504
Willy Tarreau173e7fb2012-09-24 22:47:39 +02001505 if (!newpeer->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02001506 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
1507 file, linenum, newpeer->addr.ss_family, args[2]);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto out;
1510 }
1511
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001512 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001513
1514 if (strcmp(newpeer->id, localpeer) == 0) {
1515 /* Current is local peer, it define a frontend */
1516 newpeer->local = 1;
1517
1518 if (!curpeers->peers_fe) {
1519 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1520 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1521 err_code |= ERR_ALERT | ERR_ABORT;
1522 goto out;
1523 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001524
Willy Tarreau237250c2011-07-29 01:49:03 +02001525 init_new_proxy(curpeers->peers_fe);
1526 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001527
1528 curpeers->peers_fe->last_change = now.tv_sec;
1529 curpeers->peers_fe->id = strdup(args[1]);
1530 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001531 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001532 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1533 curpeers->peers_fe->timeout.connect = 5000;
1534 curpeers->peers_fe->accept = peer_accept;
1535 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001536
1537 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1538
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001539 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &err_msg)) {
1540 if (err_msg && *err_msg) {
1541 indent_msg(&err_msg, 2);
1542 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1543 }
1544 else
1545 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1546 file, linenum, args[0], args[1], args[2]);
1547 free(err_msg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 err_code |= ERR_FATAL;
1549 goto out;
1550 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001551
1552 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1553 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1554 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1555 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1556 l->accept = session_accept;
1557 l->handler = process_session;
1558 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1559 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1560 global.maxsock += l->maxconn;
1561 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001562 }
1563 }
1564 } /* neither "peer" nor "peers" */
1565 else if (*args[0] != 0) {
1566 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1567 err_code |= ERR_ALERT | ERR_FATAL;
1568 goto out;
1569 }
1570
1571out:
1572 return err_code;
1573}
1574
1575
Willy Tarreau3842f002009-06-14 11:39:52 +02001576int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577{
1578 static struct proxy *curproxy = NULL;
1579 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001580 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001581 int rc;
1582 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001583 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001584 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001585 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001586 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001587 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588
Willy Tarreau977b8e42006-12-29 14:19:17 +01001589 if (!strcmp(args[0], "listen"))
1590 rc = PR_CAP_LISTEN;
1591 else if (!strcmp(args[0], "frontend"))
1592 rc = PR_CAP_FE | PR_CAP_RS;
1593 else if (!strcmp(args[0], "backend"))
1594 rc = PR_CAP_BE | PR_CAP_RS;
1595 else if (!strcmp(args[0], "ruleset"))
1596 rc = PR_CAP_RS;
1597 else
1598 rc = PR_CAP_NONE;
1599
1600 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 if (!*args[1]) {
1602 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1603 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001605 err_code |= ERR_ALERT | ERR_ABORT;
1606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001608
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001609 err = invalid_char(args[1]);
1610 if (err) {
1611 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1612 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001613 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001614 }
1615
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001616 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1617 /*
1618 * If there are two proxies with the same name only following
1619 * combinations are allowed:
1620 *
1621 * listen backend frontend ruleset
1622 * listen - - - -
1623 * backend - - OK -
1624 * frontend - OK - -
1625 * ruleset - - - -
1626 */
1627
1628 if (!strcmp(curproxy->id, args[1]) &&
1629 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1630 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001631 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1632 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1633 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001634 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001635 }
1636 }
1637
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1639 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001640 err_code |= ERR_ALERT | ERR_ABORT;
1641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001643
Willy Tarreau97cb7802010-01-03 20:23:58 +01001644 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001645 curproxy->next = proxy;
1646 proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001647 curproxy->conf.file = strdup(file);
Willy Tarreau90a570f2009-10-04 20:54:54 +02001648 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001649 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001651 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001652
1653 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001654 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001655 struct listener *l;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001656 char *err_msg = NULL;
Willy Tarreau81a81172012-09-18 20:52:35 +02001657
Willy Tarreau4348fad2012-09-20 16:48:07 +02001658 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1659
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001660 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &err_msg)) {
1661 if (err_msg && *err_msg) {
1662 indent_msg(&err_msg, 2);
1663 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err_msg);
1664 }
1665 else
1666 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1667 file, linenum, args[0], args[1], args[2]);
1668 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001669 err_code |= ERR_FATAL;
1670 goto out;
1671 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001672
Willy Tarreau4348fad2012-09-20 16:48:07 +02001673 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001674 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 }
1677
1678 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001679 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001680 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001681
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001684 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001685 curproxy->no_options = defproxy.no_options;
1686 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001687 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001688 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001689 curproxy->except_net = defproxy.except_net;
1690 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001691 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001692 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001693
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001694 if (defproxy.fwdfor_hdr_len) {
1695 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1696 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1697 }
1698
Willy Tarreaub86db342009-11-30 11:50:16 +01001699 if (defproxy.orgto_hdr_len) {
1700 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1701 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1702 }
1703
Mark Lamourinec2247f02012-01-04 13:02:01 -05001704 if (defproxy.server_id_hdr_len) {
1705 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1706 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1707 }
1708
Willy Tarreau977b8e42006-12-29 14:19:17 +01001709 if (curproxy->cap & PR_CAP_FE) {
1710 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001711 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001712 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001713
1714 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001715 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1716 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001717
1718 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720
Willy Tarreau977b8e42006-12-29 14:19:17 +01001721 if (curproxy->cap & PR_CAP_BE) {
1722 curproxy->fullconn = defproxy.fullconn;
1723 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001725 if (defproxy.check_req) {
1726 curproxy->check_req = calloc(1, defproxy.check_len);
1727 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1728 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001729 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001731 if (defproxy.expect_str) {
1732 curproxy->expect_str = strdup(defproxy.expect_str);
1733 if (defproxy.expect_regex) {
1734 /* note: this regex is known to be valid */
1735 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1736 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1737 }
1738 }
1739
Willy Tarreau67402132012-05-31 20:40:20 +02001740 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001741 if (defproxy.cookie_name)
1742 curproxy->cookie_name = strdup(defproxy.cookie_name);
1743 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001744 if (defproxy.cookie_domain)
1745 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001746
Willy Tarreau31936852010-10-06 16:59:56 +02001747 if (defproxy.cookie_maxidle)
1748 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1749
1750 if (defproxy.cookie_maxlife)
1751 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1752
Emeric Brun647caf12009-06-30 17:57:00 +02001753 if (defproxy.rdp_cookie_name)
1754 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1755 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1756
Willy Tarreau01732802007-11-01 22:48:15 +01001757 if (defproxy.url_param_name)
1758 curproxy->url_param_name = strdup(defproxy.url_param_name);
1759 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001760
Benoitaffb4812009-03-25 13:02:10 +01001761 if (defproxy.hh_name)
1762 curproxy->hh_name = strdup(defproxy.hh_name);
1763 curproxy->hh_len = defproxy.hh_len;
1764 curproxy->hh_match_domain = defproxy.hh_match_domain;
1765
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001766 if (defproxy.iface_name)
1767 curproxy->iface_name = strdup(defproxy.iface_name);
1768 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001771 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001772 if (defproxy.capture_name)
1773 curproxy->capture_name = strdup(defproxy.capture_name);
1774 curproxy->capture_namelen = defproxy.capture_namelen;
1775 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001776 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777
Willy Tarreau977b8e42006-12-29 14:19:17 +01001778 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001779 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001780 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001781 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001782 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001783 curproxy->uri_auth = defproxy.uri_auth;
1784 curproxy->mon_net = defproxy.mon_net;
1785 curproxy->mon_mask = defproxy.mon_mask;
1786 if (defproxy.monitor_uri)
1787 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1788 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001789 if (defproxy.defbe.name)
1790 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001791
1792 /* get either a pointer to the logformat string or a copy of it */
1793 curproxy->logformat_string = defproxy.logformat_string;
1794 if (curproxy->logformat_string &&
1795 curproxy->logformat_string != default_http_log_format &&
1796 curproxy->logformat_string != default_tcp_log_format &&
1797 curproxy->logformat_string != clf_http_log_format)
1798 curproxy->logformat_string = strdup(curproxy->logformat_string);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001799 }
1800
1801 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001802 curproxy->timeout.connect = defproxy.timeout.connect;
1803 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001804 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001805 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001806 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001807 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001808 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001809 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001810 curproxy->source_addr = defproxy.source_addr;
1811 }
1812
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001814
1815 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001816 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001817 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001818 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001819 LIST_INIT(&node->list);
1820 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1821 }
1822
Willy Tarreau196729e2012-05-31 19:30:26 +02001823 curproxy->uniqueid_format_string = defproxy.uniqueid_format_string;
1824 if (curproxy->uniqueid_format_string)
1825 curproxy->uniqueid_format_string = strdup(curproxy->uniqueid_format_string);
William Lallemanda73203e2012-03-12 12:48:57 +01001826
1827 /* copy default header unique id */
1828 if (defproxy.header_unique_id)
1829 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1830
William Lallemand82fe75c2012-10-23 10:25:10 +02001831 /* default compression options */
1832 if (defproxy.comp != NULL) {
1833 curproxy->comp = calloc(1, sizeof(struct comp));
1834 curproxy->comp->algos = defproxy.comp->algos;
1835 curproxy->comp->types = defproxy.comp->types;
1836 }
1837
Willy Tarreaubaaee002006-06-26 02:48:02 +02001838 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001839 curproxy->conf.used_listener_id = EB_ROOT;
1840 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001841
Willy Tarreau93893792009-07-23 13:19:11 +02001842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 }
1844 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1845 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001846 /* FIXME-20070101: we should do this too at the end of the
1847 * config parsing to free all default values.
1848 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001849 free(defproxy.check_req);
1850 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001851 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001852 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001853 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001854 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001855 free(defproxy.capture_name);
1856 free(defproxy.monitor_uri);
1857 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001858 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001859 free(defproxy.fwdfor_hdr_name);
1860 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001861 free(defproxy.orgto_hdr_name);
1862 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001863 free(defproxy.server_id_hdr_name);
1864 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001865 free(defproxy.expect_str);
1866 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001867
Willy Tarreau39b06652012-06-01 10:58:06 +02001868 if (defproxy.logformat_string != default_http_log_format &&
1869 defproxy.logformat_string != default_tcp_log_format &&
1870 defproxy.logformat_string != clf_http_log_format)
Willy Tarreau196729e2012-05-31 19:30:26 +02001871 free(defproxy.logformat_string);
1872
1873 free(defproxy.uniqueid_format_string);
1874
Willy Tarreaua534fea2008-08-03 12:19:50 +02001875 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001876 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001877
Willy Tarreaubaaee002006-06-26 02:48:02 +02001878 /* we cannot free uri_auth because it might already be used */
1879 init_default_instance();
1880 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001881 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001883 }
1884 else if (curproxy == NULL) {
1885 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001886 err_code |= ERR_ALERT | ERR_FATAL;
1887 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001888 }
1889
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890
1891 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001892 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001893 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001894 int cur_arg;
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001895 char *err_msg = NULL;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001896
Willy Tarreaubaaee002006-06-26 02:48:02 +02001897 if (curproxy == &defproxy) {
1898 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001903 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904
Emeric Bruned760922010-10-22 17:59:25 +02001905 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001906 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001908 err_code |= ERR_ALERT | ERR_FATAL;
1909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001911
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001912 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau290e63a2012-09-20 18:07:14 +02001913 memcpy(&bind_conf->ux, &global.unix_bind.ux, sizeof(global.unix_bind.ux));
Willy Tarreau8a956912010-10-15 14:27:08 +02001914
1915 /* NOTE: the following line might create several listeners if there
1916 * are comma-separated IPs or port ranges. So all further processing
1917 * will have to be applied to all listeners created after last_listen.
1918 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001919 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &err_msg)) {
1920 if (err_msg && *err_msg) {
1921 indent_msg(&err_msg, 2);
1922 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], err_msg);
1923 }
1924 else
1925 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
1926 file, linenum, args[0], args[1]);
1927 free(err_msg);
Willy Tarreau93893792009-07-23 13:19:11 +02001928 err_code |= ERR_ALERT | ERR_FATAL;
1929 goto out;
1930 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001931
Willy Tarreau4348fad2012-09-20 16:48:07 +02001932 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1933 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01001934 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001935 }
1936
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001937 cur_arg = 2;
1938 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02001939 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02001940 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02001941 char *err;
1942
Willy Tarreau26982662012-09-12 23:17:10 +02001943 kw = bind_find_kw(args[cur_arg]);
1944 if (kw) {
1945 char *err = NULL;
1946 int code;
1947
1948 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02001949 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
1950 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001951 cur_arg += 1 + kw->skip ;
1952 err_code |= ERR_ALERT | ERR_FATAL;
1953 goto out;
1954 }
1955
Willy Tarreau4348fad2012-09-20 16:48:07 +02001956 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02001957 err_code |= code;
1958
1959 if (code) {
1960 if (err && *err) {
1961 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02001962 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02001963 }
1964 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02001965 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
1966 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02001967 if (code & ERR_FATAL) {
1968 free(err);
1969 cur_arg += 1 + kw->skip;
1970 goto out;
1971 }
1972 }
1973 free(err);
1974 cur_arg += 1 + kw->skip;
1975 continue;
1976 }
1977
Willy Tarreau8638f482012-09-18 18:01:17 +02001978 err = NULL;
1979 if (!bind_dumped) {
1980 bind_dump_kws(&err);
1981 indent_msg(&err, 4);
1982 bind_dumped = 1;
1983 }
1984
1985 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
1986 file, linenum, args[0], args[1], args[cur_arg],
1987 err ? " Registered keywords :" : "", err ? err : "");
1988 free(err);
1989
Willy Tarreau93893792009-07-23 13:19:11 +02001990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001992 }
Willy Tarreau93893792009-07-23 13:19:11 +02001993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 }
1995 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1996 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1997 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1998 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002003 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002004
Willy Tarreaubaaee002006-06-26 02:48:02 +02002005 /* flush useless bits */
2006 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002009 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002010 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002012
Willy Tarreau1c47f852006-07-09 08:22:27 +02002013 if (!*args[1]) {
2014 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002016 err_code |= ERR_ALERT | ERR_FATAL;
2017 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002018 }
2019
Willy Tarreaua534fea2008-08-03 12:19:50 +02002020 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002021 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002022 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002023 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002024 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2025
Willy Tarreau93893792009-07-23 13:19:11 +02002026 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002027 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2029 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2030 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2031 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2032 else {
2033 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002036 }
2037 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002038 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002039 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002040
2041 if (curproxy == &defproxy) {
2042 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2043 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002046 }
2047
2048 if (!*args[1]) {
2049 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2050 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002053 }
2054
2055 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002056 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002057
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002058 if (curproxy->uuid <= 0) {
2059 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002060 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002063 }
2064
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002065 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2066 if (node) {
2067 struct proxy *target = container_of(node, struct proxy, conf.id);
2068 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2069 file, linenum, proxy_type_str(curproxy), curproxy->id,
2070 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002075 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002076 else if (!strcmp(args[0], "description")) {
2077 int i, len=0;
2078 char *d;
2079
Cyril Bonté99ed3272010-01-24 23:29:44 +01002080 if (curproxy == &defproxy) {
2081 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2082 file, linenum, args[0]);
2083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
2085 }
2086
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002087 if (!*args[1]) {
2088 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2089 file, linenum, args[0]);
2090 return -1;
2091 }
2092
2093 for(i=1; *args[i]; i++)
2094 len += strlen(args[i])+1;
2095
2096 d = (char *)calloc(1, len);
2097 curproxy->desc = d;
2098
2099 d += sprintf(d, "%s", args[1]);
2100 for(i=2; *args[i]; i++)
2101 d += sprintf(d, " %s", args[i]);
2102
2103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2105 curproxy->state = PR_STSTOPPED;
2106 }
2107 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2108 curproxy->state = PR_STNEW;
2109 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002110 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2111 int cur_arg = 1;
2112 unsigned int set = 0;
2113
2114 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002115 unsigned int low, high;
2116
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002117 if (strcmp(args[cur_arg], "all") == 0) {
2118 set = 0;
2119 break;
2120 }
2121 else if (strcmp(args[cur_arg], "odd") == 0) {
2122 set |= 0x55555555;
2123 }
2124 else if (strcmp(args[cur_arg], "even") == 0) {
2125 set |= 0xAAAAAAAA;
2126 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002127 else if (isdigit(*args[cur_arg])) {
2128 char *dash = strchr(args[cur_arg], '-');
2129
2130 low = high = str2uic(args[cur_arg]);
2131 if (dash)
2132 high = str2uic(dash + 1);
2133
2134 if (high < low) {
2135 unsigned int swap = low;
2136 low = high;
2137 high = swap;
2138 }
2139
2140 if (low < 1 || high > 32) {
2141 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002142 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002145 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002146
2147 if (high > global.nbproc) {
2148 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2149 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002151 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002152 while (low <= high)
2153 set |= 1 << (low++ - 1);
2154 }
2155 else {
2156 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2157 file, linenum, args[0]);
2158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002160 }
2161 cur_arg++;
2162 }
2163 curproxy->bind_proc = set;
2164 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002165 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002166 if (curproxy == &defproxy) {
2167 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002170 }
2171
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002172 err = invalid_char(args[1]);
2173 if (err) {
2174 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2175 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002176 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002177 }
2178
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002179 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg) == NULL) {
2180 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2181 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002184 }
2185 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2187 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002188
Willy Tarreau977b8e42006-12-29 14:19:17 +01002189 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002190 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002191
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 if (*(args[1]) == 0) {
2193 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2194 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002198
Willy Tarreau67402132012-05-31 20:40:20 +02002199 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002200 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002201 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002202 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 curproxy->cookie_name = strdup(args[1]);
2204 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002205
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 cur_arg = 2;
2207 while (*(args[cur_arg])) {
2208 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002209 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 }
2211 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002212 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 }
2214 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002215 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }
2217 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002218 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 }
2220 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002221 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002222 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002223 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002224 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002227 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002228 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002229 else if (!strcmp(args[cur_arg], "httponly")) {
2230 curproxy->ck_opts |= PR_CK_HTTPONLY;
2231 }
2232 else if (!strcmp(args[cur_arg], "secure")) {
2233 curproxy->ck_opts |= PR_CK_SECURE;
2234 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002235 else if (!strcmp(args[cur_arg], "domain")) {
2236 if (!*args[cur_arg + 1]) {
2237 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2238 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002241 }
2242
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002243 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002244 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002245 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2246 " dots nor does not start with a dot."
2247 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002248 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002249 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002250 }
2251
2252 err = invalid_domainchar(args[cur_arg + 1]);
2253 if (err) {
2254 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2255 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002258 }
2259
Willy Tarreau68a897b2009-12-03 23:28:34 +01002260 if (!curproxy->cookie_domain) {
2261 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2262 } else {
2263 /* one domain was already specified, add another one by
2264 * building the string which will be returned along with
2265 * the cookie.
2266 */
2267 char *new_ptr;
2268 int new_len = strlen(curproxy->cookie_domain) +
2269 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2270 new_ptr = malloc(new_len);
2271 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2272 free(curproxy->cookie_domain);
2273 curproxy->cookie_domain = new_ptr;
2274 }
Willy Tarreau31936852010-10-06 16:59:56 +02002275 cur_arg++;
2276 }
2277 else if (!strcmp(args[cur_arg], "maxidle")) {
2278 unsigned int maxidle;
2279 const char *res;
2280
2281 if (!*args[cur_arg + 1]) {
2282 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2283 file, linenum, args[cur_arg]);
2284 err_code |= ERR_ALERT | ERR_FATAL;
2285 goto out;
2286 }
2287
2288 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2289 if (res) {
2290 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2291 file, linenum, *res, args[cur_arg]);
2292 err_code |= ERR_ALERT | ERR_FATAL;
2293 goto out;
2294 }
2295 curproxy->cookie_maxidle = maxidle;
2296 cur_arg++;
2297 }
2298 else if (!strcmp(args[cur_arg], "maxlife")) {
2299 unsigned int maxlife;
2300 const char *res;
2301
2302 if (!*args[cur_arg + 1]) {
2303 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2304 file, linenum, args[cur_arg]);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308
2309 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2310 if (res) {
2311 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2312 file, linenum, *res, args[cur_arg]);
2313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
2315 }
2316 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002317 cur_arg++;
2318 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002320 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 +02002321 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 }
2325 cur_arg++;
2326 }
Willy Tarreau67402132012-05-31 20:40:20 +02002327 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2329 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002330 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 }
2332
Willy Tarreau67402132012-05-31 20:40:20 +02002333 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2335 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002336 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002338
Willy Tarreau67402132012-05-31 20:40:20 +02002339 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002340 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2341 file, linenum);
2342 err_code |= ERR_ALERT | ERR_FATAL;
2343 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002345 else if (!strcmp(args[0], "persist")) { /* persist */
2346 if (*(args[1]) == 0) {
2347 Alert("parsing [%s:%d] : missing persist method.\n",
2348 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002351 }
2352
2353 if (!strncmp(args[1], "rdp-cookie", 10)) {
2354 curproxy->options2 |= PR_O2_RDPC_PRST;
2355
Emeric Brunb982a3d2010-01-04 15:45:53 +01002356 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002357 const char *beg, *end;
2358
2359 beg = args[1] + 11;
2360 end = strchr(beg, ')');
2361
2362 if (!end || end == beg) {
2363 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2364 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_ALERT | ERR_FATAL;
2366 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002367 }
2368
2369 free(curproxy->rdp_cookie_name);
2370 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2371 curproxy->rdp_cookie_len = end-beg;
2372 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002373 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002374 free(curproxy->rdp_cookie_name);
2375 curproxy->rdp_cookie_name = strdup("msts");
2376 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2377 }
2378 else { /* syntax */
2379 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2380 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002383 }
2384 }
2385 else {
2386 Alert("parsing [%s:%d] : unknown persist method.\n",
2387 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002390 }
2391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002392 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002393 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002394
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002395 if (curproxy == &defproxy) {
2396 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
2400
Willy Tarreau977b8e42006-12-29 14:19:17 +01002401 if (warnifnotcap(curproxy, PR_CAP_BE, 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 (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002405 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002406 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002407 err_code |= ERR_ALERT | ERR_FATAL;
2408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 }
2410 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002411 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 curproxy->appsession_name = strdup(args[1]);
2413 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2414 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002415 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2416 if (err) {
2417 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2418 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002419 err_code |= ERR_ALERT | ERR_FATAL;
2420 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002421 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002422 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002423
Willy Tarreau51041c72007-09-09 21:56:53 +02002424 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2425 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002426 err_code |= ERR_ALERT | ERR_ABORT;
2427 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002428 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002429
2430 cur_arg = 6;
2431 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002432 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2433 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002434 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002435 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002436 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002437 } else if (!strcmp(args[cur_arg], "prefix")) {
2438 curproxy->options2 |= PR_O2_AS_PFX;
2439 } else if (!strcmp(args[cur_arg], "mode")) {
2440 if (!*args[cur_arg + 1]) {
2441 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2442 file, linenum, args[0], args[cur_arg]);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446
2447 cur_arg++;
2448 if (!strcmp(args[cur_arg], "query-string")) {
2449 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2450 curproxy->options2 |= PR_O2_AS_M_QS;
2451 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2452 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2453 curproxy->options2 |= PR_O2_AS_M_PP;
2454 } else {
2455 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002460 cur_arg++;
2461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 } /* Url App Session */
2463 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002464 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002466
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002468 if (curproxy == &defproxy) {
2469 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
2472 }
2473
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 if (*(args[4]) == 0) {
2475 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2476 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002480 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 curproxy->capture_name = strdup(args[2]);
2482 curproxy->capture_namelen = strlen(curproxy->capture_name);
2483 curproxy->capture_len = atol(args[4]);
2484 if (curproxy->capture_len >= CAPTURE_LEN) {
2485 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2486 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 curproxy->capture_len = CAPTURE_LEN - 1;
2489 }
2490 curproxy->to_log |= LW_COOKIE;
2491 }
2492 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2493 struct cap_hdr *hdr;
2494
2495 if (curproxy == &defproxy) {
2496 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 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 }
2500
2501 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2502 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2503 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002506 }
2507
2508 hdr = calloc(sizeof(struct cap_hdr), 1);
2509 hdr->next = curproxy->req_cap;
2510 hdr->name = strdup(args[3]);
2511 hdr->namelen = strlen(args[3]);
2512 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002513 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 hdr->index = curproxy->nb_req_cap++;
2515 curproxy->req_cap = hdr;
2516 curproxy->to_log |= LW_REQHDR;
2517 }
2518 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2519 struct cap_hdr *hdr;
2520
2521 if (curproxy == &defproxy) {
2522 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 +02002523 err_code |= ERR_ALERT | ERR_FATAL;
2524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525 }
2526
2527 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2528 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2529 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 }
2533 hdr = calloc(sizeof(struct cap_hdr), 1);
2534 hdr->next = curproxy->rsp_cap;
2535 hdr->name = strdup(args[3]);
2536 hdr->namelen = strlen(args[3]);
2537 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002538 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 hdr->index = curproxy->nb_rsp_cap++;
2540 curproxy->rsp_cap = hdr;
2541 curproxy->to_log |= LW_RSPHDR;
2542 }
2543 else {
2544 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2545 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 }
2549 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002550 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002551 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002553
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 if (*(args[1]) == 0) {
2555 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_FATAL;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
2560 curproxy->conn_retries = atol(args[1]);
2561 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002562 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002563 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002564
2565 if (curproxy == &defproxy) {
2566 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
2569 }
2570
Willy Tarreauff011f22011-01-06 17:51:27 +01002571 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 +01002572 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2573 file, linenum, args[0]);
2574 err_code |= ERR_WARN;
2575 }
2576
Willy Tarreauff011f22011-01-06 17:51:27 +01002577 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002578
Willy Tarreauff011f22011-01-06 17:51:27 +01002579 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002580 err_code |= ERR_ALERT | ERR_ABORT;
2581 goto out;
2582 }
2583
Willy Tarreauff011f22011-01-06 17:51:27 +01002584 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2585 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002586 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002587 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2588 /* set the header name and length into the proxy structure */
2589 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2590 err_code |= ERR_WARN;
2591
2592 if (!*args[1]) {
2593 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2594 file, linenum, args[0]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
2599 /* set the desired header name */
2600 free(curproxy->server_id_hdr_name);
2601 curproxy->server_id_hdr_name = strdup(args[1]);
2602 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2603 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002604 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002605 if (curproxy == &defproxy) {
2606 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002609 }
2610
Willy Tarreauef6494c2010-01-28 17:12:36 +01002611 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002612 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2613 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002616 }
2617
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002618 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2619 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2620 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002623 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002624
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002625 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002626 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002627 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002628 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002629 struct redirect_rule *rule;
2630 int cur_arg;
2631 int type = REDIRECT_TYPE_NONE;
2632 int code = 302;
2633 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002634 char *cookie = NULL;
2635 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002636 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002637
Cyril Bonté99ed3272010-01-24 23:29:44 +01002638 if (curproxy == &defproxy) {
2639 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002644 cur_arg = 1;
2645 while (*(args[cur_arg])) {
2646 if (!strcmp(args[cur_arg], "location")) {
2647 if (!*args[cur_arg + 1]) {
2648 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2649 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002652 }
2653
2654 type = REDIRECT_TYPE_LOCATION;
2655 cur_arg++;
2656 destination = args[cur_arg];
2657 }
2658 else if (!strcmp(args[cur_arg], "prefix")) {
2659 if (!*args[cur_arg + 1]) {
2660 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2661 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002664 }
2665
2666 type = REDIRECT_TYPE_PREFIX;
2667 cur_arg++;
2668 destination = args[cur_arg];
2669 }
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002670 else if (!strcmp(args[cur_arg], "scheme")) {
2671 if (!*args[cur_arg + 1]) {
2672 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2673 file, linenum, args[0], args[cur_arg]);
2674 err_code |= ERR_ALERT | ERR_FATAL;
2675 goto out;
2676 }
2677
2678 type = REDIRECT_TYPE_SCHEME;
2679 cur_arg++;
2680 destination = args[cur_arg];
2681 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002682 else if (!strcmp(args[cur_arg], "set-cookie")) {
2683 if (!*args[cur_arg + 1]) {
2684 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2685 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002686 err_code |= ERR_ALERT | ERR_FATAL;
2687 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002688 }
2689
2690 cur_arg++;
2691 cookie = args[cur_arg];
2692 cookie_set = 1;
2693 }
2694 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2695 if (!*args[cur_arg + 1]) {
2696 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2697 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002700 }
2701
2702 cur_arg++;
2703 cookie = args[cur_arg];
2704 cookie_set = 0;
2705 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002706 else if (!strcmp(args[cur_arg],"code")) {
2707 if (!*args[cur_arg + 1]) {
2708 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2709 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002712 }
2713 cur_arg++;
2714 code = atol(args[cur_arg]);
2715 if (code < 301 || code > 303) {
2716 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2717 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
2719 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002720 }
2721 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002722 else if (!strcmp(args[cur_arg],"drop-query")) {
2723 flags |= REDIRECT_FLAG_DROP_QS;
2724 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002725 else if (!strcmp(args[cur_arg],"append-slash")) {
2726 flags |= REDIRECT_FLAG_APPEND_SLASH;
2727 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002728 else if (strcmp(args[cur_arg], "if") == 0 ||
2729 strcmp(args[cur_arg], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002730 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg, &errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002731 if (!cond) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002732 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition : %s.\n",
2733 file, linenum, args[0], errmsg);
Willy Tarreauef6494c2010-01-28 17:12:36 +01002734 err_code |= ERR_ALERT | ERR_FATAL;
2735 goto out;
2736 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002737 break;
2738 }
2739 else {
Willy Tarreau2e1dca82012-09-12 08:43:15 +02002740 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'scheme', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002741 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002742 err_code |= ERR_ALERT | ERR_FATAL;
2743 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002744 }
2745 cur_arg++;
2746 }
2747
2748 if (type == REDIRECT_TYPE_NONE) {
2749 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2750 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002753 }
2754
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002755 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2756 rule->cond = cond;
2757 rule->rdr_str = strdup(destination);
2758 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002759 if (cookie) {
2760 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002761 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002762 */
2763 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002764 if (cookie_set) {
2765 rule->cookie_str = malloc(rule->cookie_len + 10);
2766 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2767 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2768 rule->cookie_len += 9;
2769 } else {
2770 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002771 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002772 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2773 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002774 }
2775 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002776 rule->type = type;
2777 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002778 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002779 LIST_INIT(&rule->list);
2780 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002781 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2782 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002783 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002784 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002785 struct switching_rule *rule;
2786
Willy Tarreaub099aca2008-10-12 17:26:37 +02002787 if (curproxy == &defproxy) {
2788 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002791 }
2792
Willy Tarreau55ea7572007-06-17 19:56:27 +02002793 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002795
2796 if (*(args[1]) == 0) {
2797 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002798 err_code |= ERR_ALERT | ERR_FATAL;
2799 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002800 }
2801
Willy Tarreauef6494c2010-01-28 17:12:36 +01002802 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002803 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2804 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_ALERT | ERR_FATAL;
2806 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002807 }
2808
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002809 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2810 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2811 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002812 err_code |= ERR_ALERT | ERR_FATAL;
2813 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002814 }
2815
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002816 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002817
Willy Tarreau55ea7572007-06-17 19:56:27 +02002818 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2819 rule->cond = cond;
2820 rule->be.name = strdup(args[1]);
2821 LIST_INIT(&rule->list);
2822 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2823 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002824 else if (strcmp(args[0], "use-server") == 0) {
2825 struct server_rule *rule;
2826
2827 if (curproxy == &defproxy) {
2828 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831 }
2832
2833 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2834 err_code |= ERR_WARN;
2835
2836 if (*(args[1]) == 0) {
2837 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
2840 }
2841
2842 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2843 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2844 file, linenum, args[0]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002849 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2850 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2851 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854 }
2855
2856 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2857
2858 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2859 rule->cond = cond;
2860 rule->srv.name = strdup(args[1]);
2861 LIST_INIT(&rule->list);
2862 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2863 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2864 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002865 else if ((!strcmp(args[0], "force-persist")) ||
2866 (!strcmp(args[0], "ignore-persist"))) {
2867 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002868
2869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
2875 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2876 err_code |= ERR_WARN;
2877
Willy Tarreauef6494c2010-01-28 17:12:36 +01002878 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002879 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2880 file, linenum, args[0]);
2881 err_code |= ERR_ALERT | ERR_FATAL;
2882 goto out;
2883 }
2884
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002885 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2886 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2887 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
2890 }
2891
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002892 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002893
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002894 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002895 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002896 if (!strcmp(args[0], "force-persist")) {
2897 rule->type = PERSIST_TYPE_FORCE;
2898 } else {
2899 rule->type = PERSIST_TYPE_IGNORE;
2900 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002901 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002902 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002903 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002904 else if (!strcmp(args[0], "stick-table")) {
2905 int myidx = 1;
2906
Emeric Brun32da3c42010-09-23 18:39:19 +02002907 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002908 curproxy->table.type = (unsigned int)-1;
2909 while (*args[myidx]) {
2910 const char *err;
2911
2912 if (strcmp(args[myidx], "size") == 0) {
2913 myidx++;
2914 if (!*(args[myidx])) {
2915 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2916 file, linenum, args[myidx-1]);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
2920 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2921 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2922 file, linenum, *err, args[myidx-1]);
2923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
2925 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002926 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002927 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002928 else if (strcmp(args[myidx], "peers") == 0) {
2929 myidx++;
2930 if (!*(args[myidx])) {
2931 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2932 file, linenum, args[myidx-1]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936 curproxy->table.peers.name = strdup(args[myidx++]);
2937 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002938 else if (strcmp(args[myidx], "expire") == 0) {
2939 myidx++;
2940 if (!*(args[myidx])) {
2941 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2942 file, linenum, args[myidx-1]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2947 if (err) {
2948 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2949 file, linenum, *err, args[myidx-1]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002954 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002955 }
2956 else if (strcmp(args[myidx], "nopurge") == 0) {
2957 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002958 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002959 }
2960 else if (strcmp(args[myidx], "type") == 0) {
2961 myidx++;
2962 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2963 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2964 file, linenum, args[myidx]);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
2967 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002968 /* myidx already points to next arg */
2969 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002970 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002971 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002972 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002973
2974 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002975 nw = args[myidx];
2976 while (*nw) {
2977 /* the "store" keyword supports a comma-separated list */
2978 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002979 sa = NULL; /* store arg */
2980 while (*nw && *nw != ',') {
2981 if (*nw == '(') {
2982 *nw = 0;
2983 sa = ++nw;
2984 while (*nw != ')') {
2985 if (!*nw) {
2986 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2987 file, linenum, args[0], cw);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 nw++;
2992 }
2993 *nw = '\0';
2994 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002995 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002996 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002997 if (*nw)
2998 *nw++ = '\0';
2999 type = stktable_get_data_type(cw);
3000 if (type < 0) {
3001 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3002 file, linenum, args[0], cw);
3003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
Willy Tarreauac782882010-06-20 10:41:54 +02003006
3007 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3008 switch (err) {
3009 case PE_NONE: break;
3010 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003011 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3012 file, linenum, args[0], cw);
3013 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003014 break;
3015
3016 case PE_ARG_MISSING:
3017 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3018 file, linenum, args[0], cw);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021
3022 case PE_ARG_NOT_USED:
3023 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3024 file, linenum, args[0], cw);
3025 err_code |= ERR_ALERT | ERR_FATAL;
3026 goto out;
3027
3028 default:
3029 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3030 file, linenum, args[0], cw);
3031 err_code |= ERR_ALERT | ERR_FATAL;
3032 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003033 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003034 }
3035 myidx++;
3036 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003037 else {
3038 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3039 file, linenum, args[myidx]);
3040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003042 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003043 }
3044
3045 if (!curproxy->table.size) {
3046 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3047 file, linenum);
3048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
3050 }
3051
3052 if (curproxy->table.type == (unsigned int)-1) {
3053 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3054 file, linenum);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058 }
3059 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003061 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 int myidx = 0;
3063 const char *name = NULL;
3064 int flags;
3065
3066 if (curproxy == &defproxy) {
3067 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
3070 }
3071
3072 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3073 err_code |= ERR_WARN;
3074 goto out;
3075 }
3076
3077 myidx++;
3078 if ((strcmp(args[myidx], "store") == 0) ||
3079 (strcmp(args[myidx], "store-request") == 0)) {
3080 myidx++;
3081 flags = STK_IS_STORE;
3082 }
3083 else if (strcmp(args[myidx], "store-response") == 0) {
3084 myidx++;
3085 flags = STK_IS_STORE | STK_ON_RSP;
3086 }
3087 else if (strcmp(args[myidx], "match") == 0) {
3088 myidx++;
3089 flags = STK_IS_MATCH;
3090 }
3091 else if (strcmp(args[myidx], "on") == 0) {
3092 myidx++;
3093 flags = STK_IS_MATCH | STK_IS_STORE;
3094 }
3095 else {
3096 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 if (*(args[myidx]) == 0) {
3102 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003107 expr = sample_parse_expr(args, &myidx, trash.str, trash.size);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003108 if (!expr) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +01003109 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash.str);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113
3114 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003115 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003116 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3117 file, linenum, args[0], expr->fetch->kw);
3118 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003119 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003120 goto out;
3121 }
3122 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003123 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003124 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3125 file, linenum, args[0], expr->fetch->kw);
3126 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003127 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003128 goto out;
3129 }
3130 }
3131
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003132 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
3133 if (expr->fetch->cap & SMP_CAP_L7)
3134 curproxy->acl_requires |= ACL_USE_L7_ANY;
3135
Emeric Brunb982a3d2010-01-04 15:45:53 +01003136 if (strcmp(args[myidx], "table") == 0) {
3137 myidx++;
3138 name = args[myidx++];
3139 }
3140
Willy Tarreauef6494c2010-01-28 17:12:36 +01003141 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003142 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3143 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3144 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003145 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003146 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003147 goto out;
3148 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003149 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003150 else if (*(args[myidx])) {
3151 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3152 file, linenum, args[0], args[myidx]);
3153 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003154 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003155 goto out;
3156 }
Emeric Brun97679e72010-09-23 17:56:44 +02003157 if (flags & STK_ON_RSP)
3158 err_code |= warnif_cond_requires_req(cond, file, linenum);
3159 else
3160 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003161
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3163 rule->cond = cond;
3164 rule->expr = expr;
3165 rule->flags = flags;
3166 rule->table.name = name ? strdup(name) : NULL;
3167 LIST_INIT(&rule->list);
3168 if (flags & STK_ON_RSP)
3169 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3170 else
3171 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003174 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003175 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003176
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3178 curproxy->uri_auth = NULL; /* we must detach from the default config */
3179
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003180 if (!*args[1]) {
3181 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003182 } else if (!strcmp(args[1], "admin")) {
3183 struct stats_admin_rule *rule;
3184
3185 if (curproxy == &defproxy) {
3186 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
3189 }
3190
3191 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3192 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3193 err_code |= ERR_ALERT | ERR_ABORT;
3194 goto out;
3195 }
3196
3197 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3198 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3199 file, linenum, args[0], args[1]);
3200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
3202 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003203 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3204 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3205 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003206 err_code |= ERR_ALERT | ERR_FATAL;
3207 goto out;
3208 }
3209
3210 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3211
3212 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3213 rule->cond = cond;
3214 LIST_INIT(&rule->list);
3215 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216 } else if (!strcmp(args[1], "uri")) {
3217 if (*(args[2]) == 0) {
3218 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3222 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003223 err_code |= ERR_ALERT | ERR_ABORT;
3224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 }
3226 } else if (!strcmp(args[1], "realm")) {
3227 if (*(args[2]) == 0) {
3228 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003229 err_code |= ERR_ALERT | ERR_FATAL;
3230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3232 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003236 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003237 unsigned interval;
3238
3239 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3240 if (err) {
3241 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3242 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003245 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3246 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_ABORT;
3248 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003249 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003250 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003251 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003252
3253 if (curproxy == &defproxy) {
3254 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
3258
3259 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3260 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3261 err_code |= ERR_ALERT | ERR_ABORT;
3262 goto out;
3263 }
3264
Willy Tarreauff011f22011-01-06 17:51:27 +01003265 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3266 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003267 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3268 file, linenum, args[0]);
3269 err_code |= ERR_WARN;
3270 }
3271
Willy Tarreauff011f22011-01-06 17:51:27 +01003272 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003273
Willy Tarreauff011f22011-01-06 17:51:27 +01003274 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003275 err_code |= ERR_ALERT | ERR_ABORT;
3276 goto out;
3277 }
3278
Willy Tarreauff011f22011-01-06 17:51:27 +01003279 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3280 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003281
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 } else if (!strcmp(args[1], "auth")) {
3283 if (*(args[2]) == 0) {
3284 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003285 err_code |= ERR_ALERT | ERR_FATAL;
3286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3288 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_ABORT;
3290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 }
3292 } else if (!strcmp(args[1], "scope")) {
3293 if (*(args[2]) == 0) {
3294 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003295 err_code |= ERR_ALERT | ERR_FATAL;
3296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3298 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003299 err_code |= ERR_ALERT | ERR_ABORT;
3300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 }
3302 } else if (!strcmp(args[1], "enable")) {
3303 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3304 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003305 err_code |= ERR_ALERT | ERR_ABORT;
3306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003308 } else if (!strcmp(args[1], "hide-version")) {
3309 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3310 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_ABORT;
3312 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003313 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003314 } else if (!strcmp(args[1], "show-legends")) {
3315 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3316 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3317 err_code |= ERR_ALERT | ERR_ABORT;
3318 goto out;
3319 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003320 } else if (!strcmp(args[1], "show-node")) {
3321
3322 if (*args[2]) {
3323 int i;
3324 char c;
3325
3326 for (i=0; args[2][i]; i++) {
3327 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003328 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3329 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003330 break;
3331 }
3332
3333 if (!i || args[2][i]) {
3334 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3335 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3336 file, linenum, args[0], args[1]);
3337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
3339 }
3340 }
3341
3342 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3343 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3344 err_code |= ERR_ALERT | ERR_ABORT;
3345 goto out;
3346 }
3347 } else if (!strcmp(args[1], "show-desc")) {
3348 char *desc = NULL;
3349
3350 if (*args[2]) {
3351 int i, len=0;
3352 char *d;
3353
3354 for(i=2; *args[i]; i++)
3355 len += strlen(args[i])+1;
3356
3357 desc = d = (char *)calloc(1, len);
3358
3359 d += sprintf(d, "%s", args[2]);
3360 for(i=3; *args[i]; i++)
3361 d += sprintf(d, " %s", args[i]);
3362 }
3363
3364 if (!*args[2] && !global.desc)
3365 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3366 file, linenum, args[1]);
3367 else {
3368 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3369 free(desc);
3370 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3371 err_code |= ERR_ALERT | ERR_ABORT;
3372 goto out;
3373 }
3374 free(desc);
3375 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003377stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003378 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 +01003379 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }
3383 }
3384 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003385 int optnum;
3386
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003387 if (*(args[1]) == '\0') {
3388 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3389 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003393
3394 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3395 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003396 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3397 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3398 file, linenum, cfg_opts[optnum].name);
3399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
3401 }
Willy Tarreau93893792009-07-23 13:19:11 +02003402 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3403 err_code |= ERR_WARN;
3404 goto out;
3405 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003406
Willy Tarreau3842f002009-06-14 11:39:52 +02003407 curproxy->no_options &= ~cfg_opts[optnum].val;
3408 curproxy->options &= ~cfg_opts[optnum].val;
3409
3410 switch (kwm) {
3411 case KWM_STD:
3412 curproxy->options |= cfg_opts[optnum].val;
3413 break;
3414 case KWM_NO:
3415 curproxy->no_options |= cfg_opts[optnum].val;
3416 break;
3417 case KWM_DEF: /* already cleared */
3418 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003419 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003420
Willy Tarreau93893792009-07-23 13:19:11 +02003421 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003422 }
3423 }
3424
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003425 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3426 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003427 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3428 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3429 file, linenum, cfg_opts2[optnum].name);
3430 err_code |= ERR_ALERT | ERR_FATAL;
3431 goto out;
3432 }
Willy Tarreau93893792009-07-23 13:19:11 +02003433 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3434 err_code |= ERR_WARN;
3435 goto out;
3436 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003437
Willy Tarreau3842f002009-06-14 11:39:52 +02003438 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3439 curproxy->options2 &= ~cfg_opts2[optnum].val;
3440
3441 switch (kwm) {
3442 case KWM_STD:
3443 curproxy->options2 |= cfg_opts2[optnum].val;
3444 break;
3445 case KWM_NO:
3446 curproxy->no_options2 |= cfg_opts2[optnum].val;
3447 break;
3448 case KWM_DEF: /* already cleared */
3449 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003450 }
Willy Tarreau93893792009-07-23 13:19:11 +02003451 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003452 }
3453 }
3454
Willy Tarreau3842f002009-06-14 11:39:52 +02003455 if (kwm != KWM_STD) {
3456 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003457 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003460 }
3461
Emeric Brun3a058f32009-06-30 18:26:00 +02003462 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003463 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003464 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003465 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003466 if (*(args[2]) != '\0') {
3467 if (!strcmp(args[2], "clf")) {
3468 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003469 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003470 } else {
3471 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003474 }
3475 }
Willy Tarreau196729e2012-05-31 19:30:26 +02003476 if (curproxy->logformat_string != default_http_log_format &&
3477 curproxy->logformat_string != default_tcp_log_format &&
3478 curproxy->logformat_string != clf_http_log_format)
3479 free(curproxy->logformat_string);
3480 curproxy->logformat_string = logformat;
Emeric Brun3a058f32009-06-30 18:26:00 +02003481 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003482 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 /* generate a detailed TCP log */
Willy Tarreau196729e2012-05-31 19:30:26 +02003484 if (curproxy->logformat_string != default_http_log_format &&
3485 curproxy->logformat_string != default_tcp_log_format &&
3486 curproxy->logformat_string != clf_http_log_format)
3487 free(curproxy->logformat_string);
3488 curproxy->logformat_string = default_tcp_log_format;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 else if (!strcmp(args[1], "tcpka")) {
3491 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003492 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003493 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003494
3495 if (curproxy->cap & PR_CAP_FE)
3496 curproxy->options |= PR_O_TCP_CLI_KA;
3497 if (curproxy->cap & PR_CAP_BE)
3498 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 }
3500 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003501 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_WARN;
3503
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003505 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003506 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003507 curproxy->options2 &= ~PR_O2_CHK_ANY;
3508 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 if (!*args[2]) { /* no argument */
3510 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3511 curproxy->check_len = strlen(DEF_CHECK_REQ);
3512 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003513 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003514 curproxy->check_req = (char *)malloc(reqlen);
3515 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003516 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003518 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003519 if (*args[4])
3520 reqlen += strlen(args[4]);
3521 else
3522 reqlen += strlen("HTTP/1.0");
3523
3524 curproxy->check_req = (char *)malloc(reqlen);
3525 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003526 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003528 }
3529 else if (!strcmp(args[1], "ssl-hello-chk")) {
3530 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003532 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003533
Willy Tarreaua534fea2008-08-03 12:19:50 +02003534 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003535 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003536 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003537 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 }
Willy Tarreau23677902007-05-08 23:50:35 +02003539 else if (!strcmp(args[1], "smtpchk")) {
3540 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003541 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003542 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003543 curproxy->options2 &= ~PR_O2_CHK_ANY;
3544 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003545
3546 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3547 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3548 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3549 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3550 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3551 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3552 curproxy->check_req = (char *)malloc(reqlen);
3553 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3554 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3555 } else {
3556 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3557 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3558 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3559 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3560 }
3561 }
3562 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003563 else if (!strcmp(args[1], "pgsql-check")) {
3564 /* use PostgreSQL request to check servers' health */
3565 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3566 err_code |= ERR_WARN;
3567
3568 free(curproxy->check_req);
3569 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003570 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003571 curproxy->options2 |= PR_O2_PGSQL_CHK;
3572
3573 if (*(args[2])) {
3574 int cur_arg = 2;
3575
3576 while (*(args[cur_arg])) {
3577 if (strcmp(args[cur_arg], "user") == 0) {
3578 char * packet;
3579 uint32_t packet_len;
3580 uint32_t pv;
3581
3582 /* suboption header - needs additional argument for it */
3583 if (*(args[cur_arg+1]) == 0) {
3584 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3585 file, linenum, args[0], args[1], args[cur_arg]);
3586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
3588 }
3589
3590 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3591 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3592 pv = htonl(0x30000); /* protocol version 3.0 */
3593
3594 packet = (char*) calloc(1, packet_len);
3595
3596 memcpy(packet + 4, &pv, 4);
3597
3598 /* copy "user" */
3599 memcpy(packet + 8, "user", 4);
3600
3601 /* copy username */
3602 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3603
3604 free(curproxy->check_req);
3605 curproxy->check_req = packet;
3606 curproxy->check_len = packet_len;
3607
3608 packet_len = htonl(packet_len);
3609 memcpy(packet, &packet_len, 4);
3610 cur_arg += 2;
3611 } else {
3612 /* unknown suboption - catchall */
3613 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3614 file, linenum, args[0], args[1]);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
3617 }
3618 } /* end while loop */
3619 }
3620 }
3621
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003622 else if (!strcmp(args[1], "redis-check")) {
3623 /* use REDIS PING request to check servers' health */
3624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3625 err_code |= ERR_WARN;
3626
3627 free(curproxy->check_req);
3628 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003629 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003630 curproxy->options2 |= PR_O2_REDIS_CHK;
3631
3632 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3633 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3634 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3635 }
3636
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003637 else if (!strcmp(args[1], "mysql-check")) {
3638 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3640 err_code |= ERR_WARN;
3641
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003642 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003643 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003644 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003645 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003646
3647 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3648 * const char mysql40_client_auth_pkt[] = {
3649 * "\x0e\x00\x00" // packet length
3650 * "\x01" // packet number
3651 * "\x00\x00" // client capabilities
3652 * "\x00\x00\x01" // max packet
3653 * "haproxy\x00" // username (null terminated string)
3654 * "\x00" // filler (always 0x00)
3655 * "\x01\x00\x00" // packet length
3656 * "\x00" // packet number
3657 * "\x01" // COM_QUIT command
3658 * };
3659 */
3660
3661 if (*(args[2])) {
3662 int cur_arg = 2;
3663
3664 while (*(args[cur_arg])) {
3665 if (strcmp(args[cur_arg], "user") == 0) {
3666 char *mysqluser;
3667 int packetlen, reqlen, userlen;
3668
3669 /* suboption header - needs additional argument for it */
3670 if (*(args[cur_arg+1]) == 0) {
3671 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3672 file, linenum, args[0], args[1], args[cur_arg]);
3673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
3675 }
3676 mysqluser = args[cur_arg + 1];
3677 userlen = strlen(mysqluser);
3678 packetlen = userlen + 7;
3679 reqlen = packetlen + 9;
3680
3681 free(curproxy->check_req);
3682 curproxy->check_req = (char *)calloc(1, reqlen);
3683 curproxy->check_len = reqlen;
3684
3685 snprintf(curproxy->check_req, 4, "%c%c%c",
3686 ((unsigned char) packetlen & 0xff),
3687 ((unsigned char) (packetlen >> 8) & 0xff),
3688 ((unsigned char) (packetlen >> 16) & 0xff));
3689
3690 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003691 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003692 curproxy->check_req[8] = 1;
3693 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3694 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3695 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3696 cur_arg += 2;
3697 } else {
3698 /* unknown suboption - catchall */
3699 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3700 file, linenum, args[0], args[1]);
3701 err_code |= ERR_ALERT | ERR_FATAL;
3702 goto out;
3703 }
3704 } /* end while loop */
3705 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003706 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003707 else if (!strcmp(args[1], "ldap-check")) {
3708 /* use LDAP request to check servers' health */
3709 free(curproxy->check_req);
3710 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003711 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003712 curproxy->options2 |= PR_O2_LDAP_CHK;
3713
3714 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3715 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3716 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3717 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003718 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003719 int cur_arg;
3720
3721 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3722 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003723 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003724
Willy Tarreau87cf5142011-08-19 22:57:24 +02003725 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003726
3727 free(curproxy->fwdfor_hdr_name);
3728 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3729 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3730
3731 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3732 cur_arg = 2;
3733 while (*(args[cur_arg])) {
3734 if (!strcmp(args[cur_arg], "except")) {
3735 /* suboption except - needs additional argument for it */
3736 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3737 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3738 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003739 err_code |= ERR_ALERT | ERR_FATAL;
3740 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003741 }
3742 /* flush useless bits */
3743 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003744 cur_arg += 2;
3745 } else if (!strcmp(args[cur_arg], "header")) {
3746 /* suboption header - needs additional argument for it */
3747 if (*(args[cur_arg+1]) == 0) {
3748 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3749 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_ALERT | ERR_FATAL;
3751 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003752 }
3753 free(curproxy->fwdfor_hdr_name);
3754 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3755 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3756 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003757 } else if (!strcmp(args[cur_arg], "if-none")) {
3758 curproxy->options &= ~PR_O_FF_ALWAYS;
3759 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003760 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003761 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003762 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003763 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003766 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003767 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003768 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003769 else if (!strcmp(args[1], "originalto")) {
3770 int cur_arg;
3771
3772 /* insert x-original-to field, but not for the IP address listed as an except.
3773 * set default options (ie: bitfield, header name, etc)
3774 */
3775
3776 curproxy->options |= PR_O_ORGTO;
3777
3778 free(curproxy->orgto_hdr_name);
3779 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3780 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3781
Willy Tarreau87cf5142011-08-19 22:57:24 +02003782 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003783 cur_arg = 2;
3784 while (*(args[cur_arg])) {
3785 if (!strcmp(args[cur_arg], "except")) {
3786 /* suboption except - needs additional argument for it */
3787 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3788 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3789 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003792 }
3793 /* flush useless bits */
3794 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3795 cur_arg += 2;
3796 } else if (!strcmp(args[cur_arg], "header")) {
3797 /* suboption header - needs additional argument for it */
3798 if (*(args[cur_arg+1]) == 0) {
3799 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3800 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003801 err_code |= ERR_ALERT | ERR_FATAL;
3802 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003803 }
3804 free(curproxy->orgto_hdr_name);
3805 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3806 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3807 cur_arg += 2;
3808 } else {
3809 /* unknown suboption - catchall */
3810 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3811 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003812 err_code |= ERR_ALERT | ERR_FATAL;
3813 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003814 }
3815 } /* end while loop */
3816 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003817 else {
3818 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003821 }
Willy Tarreau93893792009-07-23 13:19:11 +02003822 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003823 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003824 else if (!strcmp(args[0], "default_backend")) {
3825 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003826 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003827
3828 if (*(args[1]) == 0) {
3829 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003832 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003833 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003834 curproxy->defbe.name = strdup(args[1]);
3835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003839
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003840 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3841 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 /* enable reconnections to dispatch */
3844 curproxy->options |= PR_O_REDISP;
3845 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003846 else if (!strcmp(args[0], "http-check")) {
3847 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003849
3850 if (strcmp(args[1], "disable-on-404") == 0) {
3851 /* enable a graceful server shutdown on an HTTP 404 response */
3852 curproxy->options |= PR_O_DISABLE404;
3853 }
Willy Tarreauef781042010-01-27 11:53:01 +01003854 else if (strcmp(args[1], "send-state") == 0) {
3855 /* enable emission of the apparent state of a server in HTTP checks */
3856 curproxy->options2 |= PR_O2_CHK_SNDST;
3857 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003858 else if (strcmp(args[1], "expect") == 0) {
3859 const char *ptr_arg;
3860 int cur_arg;
3861
3862 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3863 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
3866 }
3867
3868 cur_arg = 2;
3869 /* consider exclamation marks, sole or at the beginning of a word */
3870 while (*(ptr_arg = args[cur_arg])) {
3871 while (*ptr_arg == '!') {
3872 curproxy->options2 ^= PR_O2_EXP_INV;
3873 ptr_arg++;
3874 }
3875 if (*ptr_arg)
3876 break;
3877 cur_arg++;
3878 }
3879 /* now ptr_arg points to the beginning of a word past any possible
3880 * exclamation mark, and cur_arg is the argument which holds this word.
3881 */
3882 if (strcmp(ptr_arg, "status") == 0) {
3883 if (!*(args[cur_arg + 1])) {
3884 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3885 file, linenum, args[0], args[1], ptr_arg);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003890 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003891 curproxy->expect_str = strdup(args[cur_arg + 1]);
3892 }
3893 else if (strcmp(ptr_arg, "string") == 0) {
3894 if (!*(args[cur_arg + 1])) {
3895 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3896 file, linenum, args[0], args[1], ptr_arg);
3897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
3899 }
3900 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003901 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003902 curproxy->expect_str = strdup(args[cur_arg + 1]);
3903 }
3904 else if (strcmp(ptr_arg, "rstatus") == 0) {
3905 if (!*(args[cur_arg + 1])) {
3906 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3907 file, linenum, args[0], args[1], ptr_arg);
3908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
3910 }
3911 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003912 free(curproxy->expect_str);
3913 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3914 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003915 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3916 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3917 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3918 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922 }
3923 else if (strcmp(ptr_arg, "rstring") == 0) {
3924 if (!*(args[cur_arg + 1])) {
3925 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3926 file, linenum, args[0], args[1], ptr_arg);
3927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
3929 }
3930 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003931 free(curproxy->expect_str);
3932 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3933 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003934 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3935 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3936 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3937 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
3940 }
3941 }
3942 else {
3943 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3944 file, linenum, args[0], args[1], ptr_arg);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003949 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003950 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 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003953 }
3954 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003955 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003956 if (curproxy == &defproxy) {
3957 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003958 err_code |= ERR_ALERT | ERR_FATAL;
3959 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003960 }
3961
Willy Tarreaub80c2302007-11-30 20:51:32 +01003962 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003964
3965 if (strcmp(args[1], "fail") == 0) {
3966 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003967 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003968 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3969 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003972 }
3973
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003974 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3975 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
3976 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003979 }
3980 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3981 }
3982 else {
3983 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003984 err_code |= ERR_ALERT | ERR_FATAL;
3985 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003986 }
3987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003988#ifdef TPROXY
3989 else if (!strcmp(args[0], "transparent")) {
3990 /* enable transparent proxy connections */
3991 curproxy->options |= PR_O_TRANSP;
3992 }
3993#endif
3994 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003995 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003997
Willy Tarreaubaaee002006-06-26 02:48:02 +02003998 if (*(args[1]) == 0) {
3999 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004002 }
4003 curproxy->maxconn = atol(args[1]);
4004 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004005 else if (!strcmp(args[0], "backlog")) { /* backlog */
4006 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004008
4009 if (*(args[1]) == 0) {
4010 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004013 }
4014 curproxy->backlog = atol(args[1]);
4015 }
Willy Tarreau86034312006-12-29 00:10:33 +01004016 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004017 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004019
Willy Tarreau86034312006-12-29 00:10:33 +01004020 if (*(args[1]) == 0) {
4021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004024 }
4025 curproxy->fullconn = atol(args[1]);
4026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004027 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4028 if (*(args[1]) == 0) {
4029 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004033 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4034 if (err) {
4035 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4036 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004039 }
4040 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004041 }
4042 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004043 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 if (curproxy == &defproxy) {
4045 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004049 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004050 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004051
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 if (strchr(args[1], ':') == NULL) {
4053 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004054 err_code |= ERR_ALERT | ERR_FATAL;
4055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004056 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01004057 sk = str2sa(args[1]);
4058 if (!sk) {
4059 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004064 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004065 }
4066 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004067 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004068 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004069
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004070 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4071 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004072 err_code |= ERR_ALERT | ERR_FATAL;
4073 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004076 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
4077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4078 err_code |= ERR_WARN;
4079
4080 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
4081 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4082 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4083 }
4084 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
4085 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4086 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4087 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01004088 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
4089 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
4090 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
4091 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004092 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01004093 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
4097 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004098 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004100 char *rport, *raddr;
4101 short realport = 0;
4102 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004104 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004105 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004106 err_code |= ERR_ALERT | ERR_FATAL;
4107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004108 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004109 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004110 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111
4112 if (!*args[2]) {
4113 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4114 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004118
4119 err = invalid_char(args[1]);
4120 if (err) {
4121 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4122 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004125 }
4126
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004127 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004128 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004129
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004130 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4131 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4132 err_code |= ERR_ALERT | ERR_ABORT;
4133 goto out;
4134 }
4135
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004136 /* the servers are linked backwards first */
4137 newsrv->next = curproxy->srv;
4138 curproxy->srv = newsrv;
4139 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004140 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004141 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004143 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004144 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004145 LIST_INIT(&newsrv->pendconns);
4146 do_check = 0;
4147 newsrv->state = SRV_RUNNING; /* early server setup */
4148 newsrv->last_change = now.tv_sec;
4149 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004151 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004152 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004153 * - IP: => port=+0, relative
4154 * - IP:N => port=N, absolute
4155 * - IP:+N => port=+N, relative
4156 * - IP:-N => port=-N, relative
4157 */
4158 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004159 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004160 if (rport) {
4161 *rport++ = 0;
4162 realport = atol(rport);
4163 if (!isdigit((unsigned char)*rport))
4164 newsrv->state |= SRV_MAPPORTS;
4165 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004167
Willy Tarreaufab5a432011-03-04 15:31:53 +01004168 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004169 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004170 if (!sk) {
4171 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
4174 }
4175 newsrv->addr = *sk;
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004176 newsrv->proto = newsrv->check.proto = protocol_by_family(newsrv->addr.ss_family);
4177 newsrv->xprt = newsrv->check.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004178
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004179 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004180 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4181 file, linenum, newsrv->addr.ss_family, args[2]);
4182 err_code |= ERR_ALERT | ERR_FATAL;
4183 goto out;
4184 }
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004185 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004186
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004187 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004188 newsrv->check.port = curproxy->defsrv.check.port;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004189 newsrv->inter = curproxy->defsrv.inter;
4190 newsrv->fastinter = curproxy->defsrv.fastinter;
4191 newsrv->downinter = curproxy->defsrv.downinter;
4192 newsrv->rise = curproxy->defsrv.rise;
4193 newsrv->fall = curproxy->defsrv.fall;
4194 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4195 newsrv->minconn = curproxy->defsrv.minconn;
4196 newsrv->maxconn = curproxy->defsrv.maxconn;
4197 newsrv->slowstart = curproxy->defsrv.slowstart;
4198 newsrv->onerror = curproxy->defsrv.onerror;
4199 newsrv->consecutive_errors_limit
4200 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004201#ifdef OPENSSL
4202 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4203#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004204 newsrv->uweight = newsrv->iweight
4205 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004206
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004207 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004209 cur_arg = 3;
4210 } else {
4211 newsrv = &curproxy->defsrv;
4212 cur_arg = 1;
4213 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004214
Willy Tarreaubaaee002006-06-26 02:48:02 +02004215 while (*args[cur_arg]) {
Willy Tarreaudff55432012-10-10 17:51:05 +02004216 if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004217 newsrv->cookie = strdup(args[cur_arg + 1]);
4218 newsrv->cklen = strlen(args[cur_arg + 1]);
4219 cur_arg += 2;
4220 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004221 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004222 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4223 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4224 cur_arg += 2;
4225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004227 if (!*args[cur_arg + 1]) {
4228 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4229 file, linenum, args[cur_arg]);
4230 err_code |= ERR_ALERT | ERR_FATAL;
4231 goto out;
4232 }
4233
Willy Tarreaubaaee002006-06-26 02:48:02 +02004234 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004235 if (newsrv->rise <= 0) {
4236 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4237 file, linenum, args[cur_arg]);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
4240 }
4241
Willy Tarreau96839092010-03-29 10:02:24 +02004242 if (newsrv->health)
4243 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 cur_arg += 2;
4245 }
4246 else if (!strcmp(args[cur_arg], "fall")) {
4247 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004248
4249 if (!*args[cur_arg + 1]) {
4250 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4251 file, linenum, args[cur_arg]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
4254 }
4255
4256 if (newsrv->fall <= 0) {
4257 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4258 file, linenum, args[cur_arg]);
4259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
4262
Willy Tarreaubaaee002006-06-26 02:48:02 +02004263 cur_arg += 2;
4264 }
4265 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004266 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4267 if (err) {
4268 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4269 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004270 err_code |= ERR_ALERT | ERR_FATAL;
4271 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004272 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004273 if (val <= 0) {
4274 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4275 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004278 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004279 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 cur_arg += 2;
4281 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004282 else if (!strcmp(args[cur_arg], "fastinter")) {
4283 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4284 if (err) {
4285 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4286 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004287 err_code |= ERR_ALERT | ERR_FATAL;
4288 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004289 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004290 if (val <= 0) {
4291 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4292 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004295 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004296 newsrv->fastinter = val;
4297 cur_arg += 2;
4298 }
4299 else if (!strcmp(args[cur_arg], "downinter")) {
4300 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4301 if (err) {
4302 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4303 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004306 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004307 if (val <= 0) {
4308 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4309 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004312 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004313 newsrv->downinter = val;
4314 cur_arg += 2;
4315 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004316 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004317 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004318 if (!sk) {
4319 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4320 err_code |= ERR_ALERT | ERR_FATAL;
4321 goto out;
4322 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004323 newsrv->check.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004324 cur_arg += 2;
4325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004326 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004327 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004328 cur_arg += 2;
4329 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004330 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 newsrv->state |= SRV_BACKUP;
4332 cur_arg ++;
4333 }
Simon Hormanfa461682011-06-25 09:39:49 +09004334 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4335 newsrv->state |= SRV_NON_STICK;
4336 cur_arg ++;
4337 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004338 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4339 newsrv->state |= SRV_SEND_PROXY;
4340 cur_arg ++;
4341 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004342 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4343 newsrv->check.send_proxy = 1;
4344 cur_arg ++;
4345 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 else if (!strcmp(args[cur_arg], "weight")) {
4347 int w;
4348 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004349 if (w < 0 || w > 256) {
4350 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004352 err_code |= ERR_ALERT | ERR_FATAL;
4353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004354 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004355 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356 cur_arg += 2;
4357 }
4358 else if (!strcmp(args[cur_arg], "minconn")) {
4359 newsrv->minconn = atol(args[cur_arg + 1]);
4360 cur_arg += 2;
4361 }
4362 else if (!strcmp(args[cur_arg], "maxconn")) {
4363 newsrv->maxconn = atol(args[cur_arg + 1]);
4364 cur_arg += 2;
4365 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004366 else if (!strcmp(args[cur_arg], "maxqueue")) {
4367 newsrv->maxqueue = atol(args[cur_arg + 1]);
4368 cur_arg += 2;
4369 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004370 else if (!strcmp(args[cur_arg], "slowstart")) {
4371 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004372 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004373 if (err) {
4374 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4375 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004378 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004379 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004380 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4381 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004384 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004385 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004386 cur_arg += 2;
4387 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004388 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004389
4390 if (!*args[cur_arg + 1]) {
4391 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4392 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004393 err_code |= ERR_ALERT | ERR_FATAL;
4394 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004395 }
4396
4397 newsrv->trackit = strdup(args[cur_arg + 1]);
4398
4399 cur_arg += 2;
4400 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004401 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 global.maxsock++;
4403 do_check = 1;
4404 cur_arg += 1;
4405 }
Willy Tarreau96839092010-03-29 10:02:24 +02004406 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4407 newsrv->state |= SRV_MAINTAIN;
4408 newsrv->state &= ~SRV_RUNNING;
4409 newsrv->health = 0;
4410 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004411 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004412 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004413 if (!strcmp(args[cur_arg + 1], "none"))
4414 newsrv->observe = HANA_OBS_NONE;
4415 else if (!strcmp(args[cur_arg + 1], "layer4"))
4416 newsrv->observe = HANA_OBS_LAYER4;
4417 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4418 if (curproxy->mode != PR_MODE_HTTP) {
4419 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4420 file, linenum, args[cur_arg + 1]);
4421 err_code |= ERR_ALERT;
4422 }
4423 newsrv->observe = HANA_OBS_LAYER7;
4424 }
4425 else {
4426 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004427 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004428 file, linenum, args[cur_arg], args[cur_arg + 1]);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
4432
4433 cur_arg += 2;
4434 }
4435 else if (!strcmp(args[cur_arg], "on-error")) {
4436 if (!strcmp(args[cur_arg + 1], "fastinter"))
4437 newsrv->onerror = HANA_ONERR_FASTINTER;
4438 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4439 newsrv->onerror = HANA_ONERR_FAILCHK;
4440 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4441 newsrv->onerror = HANA_ONERR_SUDDTH;
4442 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4443 newsrv->onerror = HANA_ONERR_MARKDWN;
4444 else {
4445 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004446 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004447 file, linenum, args[cur_arg], args[cur_arg + 1]);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 }
4451
4452 cur_arg += 2;
4453 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004454 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4455 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4456 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4457 else {
4458 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4459 file, linenum, args[cur_arg], args[cur_arg + 1]);
4460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
4462 }
4463
4464 cur_arg += 2;
4465 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004466 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4467 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4468 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4469 else {
4470 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4471 file, linenum, args[cur_arg], args[cur_arg + 1]);
4472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
4474 }
4475
4476 cur_arg += 2;
4477 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004478 else if (!strcmp(args[cur_arg], "error-limit")) {
4479 if (!*args[cur_arg + 1]) {
4480 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4481 file, linenum, args[cur_arg]);
4482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
4484 }
4485
4486 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4487
4488 if (newsrv->consecutive_errors_limit <= 0) {
4489 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4490 file, linenum, args[cur_arg]);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004494 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004495 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004496 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004497 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004498 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004499
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004501#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004502 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004503 file, linenum, "source", "usesrc");
4504#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004505 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004506 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004507#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 }
4511 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004512 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4513 if (!sk) {
4514 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4515 err_code |= ERR_ALERT | ERR_FATAL;
4516 goto out;
4517 }
4518 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004519
4520 if (port_low != port_high) {
4521 int i;
4522 if (port_low <= 0 || port_low > 65535 ||
4523 port_high <= 0 || port_high > 65535 ||
4524 port_low > port_high) {
4525 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4526 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004527 err_code |= ERR_ALERT | ERR_FATAL;
4528 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004529 }
4530 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4531 for (i = 0; i < newsrv->sport_range->size; i++)
4532 newsrv->sport_range->ports[i] = port_low + i;
4533 }
4534
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004536 while (*(args[cur_arg])) {
4537 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004538#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4539#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004540 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4541 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4542 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004543 err_code |= ERR_ALERT | ERR_FATAL;
4544 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004545 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004546#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004547 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004548 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004549 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004552 }
4553 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004554 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004555 newsrv->state |= SRV_TPROXY_CLI;
4556 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004557 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004558 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004559 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4560 char *name, *end;
4561
4562 name = args[cur_arg+1] + 7;
4563 while (isspace(*name))
4564 name++;
4565
4566 end = name;
4567 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4568 end++;
4569
4570 newsrv->state &= ~SRV_TPROXY_MASK;
4571 newsrv->state |= SRV_TPROXY_DYN;
4572 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4573 newsrv->bind_hdr_len = end - name;
4574 memcpy(newsrv->bind_hdr_name, name, end - name);
4575 newsrv->bind_hdr_name[end-name] = '\0';
4576 newsrv->bind_hdr_occ = -1;
4577
4578 /* now look for an occurrence number */
4579 while (isspace(*end))
4580 end++;
4581 if (*end == ',') {
4582 end++;
4583 name = end;
4584 if (*end == '-')
4585 end++;
4586 while (isdigit(*end))
4587 end++;
4588 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4589 }
4590
4591 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4592 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4593 " occurrences values smaller than %d.\n",
4594 file, linenum, MAX_HDR_HISTORY);
4595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
4597 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004598 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004599 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004600 if (!sk) {
4601 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604 }
4605 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004606 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004607 }
4608 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004609#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004610 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004611#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004612 cur_arg += 2;
4613 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004614#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004615 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004616 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004619#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4620 } /* "usesrc" */
4621
4622 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4623#ifdef SO_BINDTODEVICE
4624 if (!*args[cur_arg + 1]) {
4625 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004627 err_code |= ERR_ALERT | ERR_FATAL;
4628 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004629 }
4630 if (newsrv->iface_name)
4631 free(newsrv->iface_name);
4632
4633 newsrv->iface_name = strdup(args[cur_arg + 1]);
4634 newsrv->iface_len = strlen(newsrv->iface_name);
4635 global.last_checks |= LSTCHK_NETADM;
4636#else
4637 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4638 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004641#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004642 cur_arg += 2;
4643 continue;
4644 }
4645 /* this keyword in not an option of "source" */
4646 break;
4647 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004649 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004650 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4651 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004655 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02004656 static int srv_dumped;
4657 struct srv_kw *kw;
4658 char *err;
4659
4660 kw = srv_find_kw(args[cur_arg]);
4661 if (kw) {
4662 char *err = NULL;
4663 int code;
4664
4665 if (!kw->parse) {
4666 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
4667 file, linenum, args[0], args[1], args[cur_arg]);
4668 cur_arg += 1 + kw->skip ;
4669 err_code |= ERR_ALERT | ERR_FATAL;
4670 goto out;
4671 }
4672
4673 if (defsrv && !kw->default_ok) {
4674 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
4675 file, linenum, args[0], args[1], args[cur_arg]);
4676 cur_arg += 1 + kw->skip ;
4677 err_code |= ERR_ALERT;
4678 continue;
4679 }
4680
4681 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
4682 err_code |= code;
4683
4684 if (code) {
4685 if (err && *err) {
4686 indent_msg(&err, 2);
4687 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
4688 }
4689 else
4690 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
4691 file, linenum, args[0], args[1], args[cur_arg]);
4692 if (code & ERR_FATAL) {
4693 free(err);
4694 cur_arg += 1 + kw->skip;
4695 goto out;
4696 }
4697 }
4698 free(err);
4699 cur_arg += 1 + kw->skip;
4700 continue;
4701 }
4702
4703 err = NULL;
4704 if (!srv_dumped) {
4705 srv_dump_kws(&err);
4706 indent_msg(&err, 4);
4707 srv_dumped = 1;
4708 }
4709
4710 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
4711 file, linenum, args[0], args[1], args[cur_arg],
4712 err ? " Registered keywords :" : "", err ? err : "");
4713 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004714
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 }
4718 }
4719
4720 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004721 if (newsrv->trackit) {
4722 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4723 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004726 }
4727
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004728 /* If neither a port nor an addr was specified and no check transport
4729 * layer is forced, then the transport layer used by the checks is the
4730 * same as for the production traffic. Otherwise we use raw_sock by
4731 * default, unless one is specified.
4732 */
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004733 if (!newsrv->check.port && !is_addr(&newsrv->check.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02004734#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02004735 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02004736#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004737 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
4738 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004739 /* try to get the port from check.addr if check.port not set */
4740 if (!newsrv->check.port)
4741 newsrv->check.port = get_host_port(&newsrv->check.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004742
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004743 if (!newsrv->check.port && !(newsrv->state & SRV_MAPPORTS))
4744 newsrv->check.port = realport; /* by default */
4745 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004746 /* not yet valid, because no port was set on
4747 * the server either. We'll check if we have
4748 * a known port on the first listener.
4749 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02004750 struct listener *l;
4751
4752 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004753 newsrv->check.port = get_host_port(&l->addr);
4754 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02004755 break;
4756 }
Willy Tarreauef00b502007-01-07 02:40:09 +01004757 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004758 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004759 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4760 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004764
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004765 /* Allocate buffer for check requests... */
4766 if ((newsrv->check.bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004767 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4768 err_code |= ERR_ALERT | ERR_ABORT;
4769 goto out;
4770 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02004771 newsrv->check.bi->size = global.tune.chksize;
4772
4773 /* Allocate buffer for check responses... */
4774 if ((newsrv->check.bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
4775 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4776 err_code |= ERR_ALERT | ERR_ABORT;
4777 goto out;
4778 }
4779 newsrv->check.bo->size = global.tune.chksize;
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004780
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004781 /* Allocate buffer for partial check results... */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004782 if ((newsrv->check.conn = calloc(1, sizeof(struct connection))) == NULL) {
Willy Tarreauda92e2f2012-07-06 09:40:59 +02004783 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
4784 err_code |= ERR_ALERT | ERR_ABORT;
4785 goto out;
4786 }
4787
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004788 newsrv->check.conn->t.sock.fd = -1; /* no check in progress yet */
4789 newsrv->check.status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004790 newsrv->state |= SRV_CHECKED;
4791 }
4792
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004793 if (!defsrv) {
4794 if (newsrv->state & SRV_BACKUP)
4795 curproxy->srv_bck++;
4796 else
4797 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004798
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004799 newsrv->prev_state = newsrv->state;
4800 }
William Lallemanda73203e2012-03-12 12:48:57 +01004801 }
4802
4803 else if (strcmp(args[0], "unique-id-format") == 0) {
4804 if (!*(args[1])) {
4805 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
4808 }
William Lallemand3203ff42012-11-11 17:30:56 +01004809 if (*(args[2])) {
4810 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4811 err_code |= ERR_ALERT | ERR_FATAL;
4812 goto out;
4813 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004814 free(curproxy->uniqueid_format_string);
4815 curproxy->uniqueid_format_string = strdup(args[1]);
William Lallemand723b73a2012-02-08 16:37:49 +01004816 }
William Lallemanda73203e2012-03-12 12:48:57 +01004817
4818 else if (strcmp(args[0], "unique-id-header") == 0) {
4819 if (!*(args[1])) {
4820 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823 }
4824 free(curproxy->header_unique_id);
4825 curproxy->header_unique_id = strdup(args[1]);
4826 }
4827
William Lallemand723b73a2012-02-08 16:37:49 +01004828 else if (strcmp(args[0], "log-format") == 0) {
4829 if (!*(args[1])) {
4830 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
William Lallemand3203ff42012-11-11 17:30:56 +01004834 if (*(args[2])) {
4835 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004839
4840 if (curproxy->logformat_string != default_http_log_format &&
4841 curproxy->logformat_string != default_tcp_log_format &&
4842 curproxy->logformat_string != clf_http_log_format)
4843 free(curproxy->logformat_string);
4844 curproxy->logformat_string = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 }
William Lallemand723b73a2012-02-08 16:37:49 +01004846
William Lallemand0f99e342011-10-12 17:50:54 +02004847 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4848 /* delete previous herited or defined syslog servers */
4849 struct logsrv *back;
4850
4851 if (*(args[1]) != 0) {
4852 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
4855 }
4856
William Lallemand723b73a2012-02-08 16:37:49 +01004857 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4858 LIST_DEL(&tmplogsrv->list);
4859 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004860 }
4861 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004863 struct logsrv *logsrv;
4864
Willy Tarreaubaaee002006-06-26 02:48:02 +02004865 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004866 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004867 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004868 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004869 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004870 LIST_INIT(&node->list);
4871 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 }
4874 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004875
4876 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877
William Lallemand0f99e342011-10-12 17:50:54 +02004878 logsrv->facility = get_log_facility(args[2]);
4879 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004880 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
4883
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 }
4885
William Lallemand0f99e342011-10-12 17:50:54 +02004886 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004887 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004888 logsrv->level = get_log_level(args[3]);
4889 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004891 err_code |= ERR_ALERT | ERR_FATAL;
4892 goto out;
4893
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 }
4895 }
4896
William Lallemand0f99e342011-10-12 17:50:54 +02004897 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004898 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004899 logsrv->minlvl = get_log_level(args[4]);
4900 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004901 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
4904
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004905 }
4906 }
4907
Robert Tsai81ae1952007-12-05 10:47:29 +01004908 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004909 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004910 if (!sk) {
4911 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004912 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
4915 }
William Lallemand0f99e342011-10-12 17:50:54 +02004916 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004917 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004918 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004919 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004920 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923 }
William Lallemand0f99e342011-10-12 17:50:54 +02004924 logsrv->addr = *sk;
4925 if (!get_host_port(&logsrv->addr))
4926 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004927 }
William Lallemand0f99e342011-10-12 17:50:54 +02004928
4929 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931 else {
4932 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4933 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
4937 }
4938 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004939 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004940 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004941
Willy Tarreau977b8e42006-12-29 14:19:17 +01004942 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004944
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004946 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4947 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004948 err_code |= ERR_ALERT | ERR_FATAL;
4949 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004951
4952 /* we must first clear any optional default setting */
4953 curproxy->options &= ~PR_O_TPXY_MASK;
4954 free(curproxy->iface_name);
4955 curproxy->iface_name = NULL;
4956 curproxy->iface_len = 0;
4957
Willy Tarreaud5191e72010-02-09 20:50:45 +01004958 sk = str2sa(args[1]);
4959 if (!sk) {
4960 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
4963 }
4964 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004966
4967 cur_arg = 2;
4968 while (*(args[cur_arg])) {
4969 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004970#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4971#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004972 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4973 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4974 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004977 }
4978#endif
4979 if (!*args[cur_arg + 1]) {
4980 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4981 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004982 err_code |= ERR_ALERT | ERR_FATAL;
4983 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004984 }
4985
4986 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004987 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004988 curproxy->options |= PR_O_TPXY_CLI;
4989 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004990 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004991 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004992 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4993 char *name, *end;
4994
4995 name = args[cur_arg+1] + 7;
4996 while (isspace(*name))
4997 name++;
4998
4999 end = name;
5000 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5001 end++;
5002
5003 curproxy->options &= ~PR_O_TPXY_MASK;
5004 curproxy->options |= PR_O_TPXY_DYN;
5005 curproxy->bind_hdr_name = calloc(1, end - name + 1);
5006 curproxy->bind_hdr_len = end - name;
5007 memcpy(curproxy->bind_hdr_name, name, end - name);
5008 curproxy->bind_hdr_name[end-name] = '\0';
5009 curproxy->bind_hdr_occ = -1;
5010
5011 /* now look for an occurrence number */
5012 while (isspace(*end))
5013 end++;
5014 if (*end == ',') {
5015 end++;
5016 name = end;
5017 if (*end == '-')
5018 end++;
5019 while (isdigit(*end))
5020 end++;
5021 curproxy->bind_hdr_occ = strl2ic(name, end-name);
5022 }
5023
5024 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
5025 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5026 " occurrences values smaller than %d.\n",
5027 file, linenum, MAX_HDR_HISTORY);
5028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
5030 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005031 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01005032 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005033 if (!sk) {
5034 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
5035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
5037 }
5038 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005039 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005040 }
5041 global.last_checks |= LSTCHK_NETADM;
5042#if !defined(CONFIG_HAP_LINUX_TPROXY)
5043 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005044#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005045#else /* no TPROXY support */
5046 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005047 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005050#endif
5051 cur_arg += 2;
5052 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005053 }
5054
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005055 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5056#ifdef SO_BINDTODEVICE
5057 if (!*args[cur_arg + 1]) {
5058 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5059 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005062 }
5063 if (curproxy->iface_name)
5064 free(curproxy->iface_name);
5065
5066 curproxy->iface_name = strdup(args[cur_arg + 1]);
5067 curproxy->iface_len = strlen(curproxy->iface_name);
5068 global.last_checks |= LSTCHK_NETADM;
5069#else
5070 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5071 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005074#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005075 cur_arg += 2;
5076 continue;
5077 }
5078 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005079 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005080 err_code |= ERR_ALERT | ERR_FATAL;
5081 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005082 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005083 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005084 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5085 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5086 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005087 err_code |= ERR_ALERT | ERR_FATAL;
5088 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005089 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005091 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5093 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005094 err_code |= ERR_ALERT | ERR_FATAL;
5095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005096 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005097
5098 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005099 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005100 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005101 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005103 }
5104 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005105 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005106 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005107 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005108 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005110 }
5111 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005112 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005113 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005114 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005115 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005117 }
5118 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005119 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005120 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005121 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005122 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005124 }
5125 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005126 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005127 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005128 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005129 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005131 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005132 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005133 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005134 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005135 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005136 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005137 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005138 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005139 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005140 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005141 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005142 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005143 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005144 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005145 }
5146 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005147 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005148 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005149 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005150 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005151 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005152 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005153 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005154 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5156 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005160
5161 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005162 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005163 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005166 }
5167 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005169 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005170 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005171 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
5174 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005175 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005176 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005177 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005183 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005184 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
5188 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005190 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005191 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005195 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005197 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005198 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005200 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005202 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005203 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005204
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 if (curproxy == &defproxy) {
5206 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005210 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212
Willy Tarreaubaaee002006-06-26 02:48:02 +02005213 if (*(args[1]) == 0) {
5214 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005215 err_code |= ERR_ALERT | ERR_FATAL;
5216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005217 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005218
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005219 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005220 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5221 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5222 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005223 err_code |= ERR_ALERT | ERR_FATAL;
5224 goto out;
5225 }
5226 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5227 }
5228 else if (*args[2]) {
5229 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5230 file, linenum, args[0], args[2]);
5231 err_code |= ERR_ALERT | ERR_FATAL;
5232 goto out;
5233 }
5234
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005235 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005236 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005237 wl->s = strdup(args[1]);
5238 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005239 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 }
5241 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005243 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5244 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005245 err_code |= ERR_ALERT | ERR_FATAL;
5246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005247 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005248
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005250 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005251 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005252 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254 }
5255 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005257 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005258 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005259 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005261 }
5262 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005264 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005265 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
5269 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5272 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005273 err_code |= ERR_ALERT | ERR_FATAL;
5274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 }
5276
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005278 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005279 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005280 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282 }
5283 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005285 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005286 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
5290 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005292 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005293 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
5297 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005298 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005299
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 if (curproxy == &defproxy) {
5301 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005305 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005306 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005307
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 if (*(args[1]) == 0) {
5309 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005312 }
5313
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005314 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005315 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5316 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5317 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005318 err_code |= ERR_ALERT | ERR_FATAL;
5319 goto out;
5320 }
5321 err_code |= warnif_cond_requires_req(cond, file, linenum);
5322 }
5323 else if (*args[2]) {
5324 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5325 file, linenum, args[0], args[2]);
5326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 }
5329
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005330 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005331 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005332 wl->s = strdup(args[1]);
5333 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 }
5335 else if (!strcmp(args[0], "errorloc") ||
5336 !strcmp(args[0], "errorloc302") ||
5337 !strcmp(args[0], "errorloc303")) { /* error location */
5338 int errnum, errlen;
5339 char *err;
5340
Willy Tarreau977b8e42006-12-29 14:19:17 +01005341 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005342 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005343
Willy Tarreaubaaee002006-06-26 02:48:02 +02005344 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005345 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005346 err_code |= ERR_ALERT | ERR_FATAL;
5347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
5349
5350 errnum = atol(args[1]);
5351 if (!strcmp(args[0], "errorloc303")) {
5352 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5353 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5354 } else {
5355 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5356 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5357 }
5358
Willy Tarreau0f772532006-12-23 20:51:41 +01005359 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5360 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005361 chunk_destroy(&curproxy->errmsg[rc]);
5362 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005363 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005365 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005366
5367 if (rc >= HTTP_ERR_SIZE) {
5368 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5369 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 free(err);
5371 }
5372 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005373 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5374 int errnum, errlen, fd;
5375 char *err;
5376 struct stat stat;
5377
5378 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005380
5381 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005382 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005385 }
5386
5387 fd = open(args[2], O_RDONLY);
5388 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5389 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5390 file, linenum, args[2], args[1]);
5391 if (fd >= 0)
5392 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005395 }
5396
Willy Tarreau27a674e2009-08-17 07:23:33 +02005397 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005398 errlen = stat.st_size;
5399 } else {
5400 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005401 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005402 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005403 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005404 }
5405
5406 err = malloc(errlen); /* malloc() must succeed during parsing */
5407 errnum = read(fd, err, errlen);
5408 if (errnum != errlen) {
5409 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5410 file, linenum, args[2], args[1]);
5411 close(fd);
5412 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005415 }
5416 close(fd);
5417
5418 errnum = atol(args[1]);
5419 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5420 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005421 chunk_destroy(&curproxy->errmsg[rc]);
5422 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005423 break;
5424 }
5425 }
5426
5427 if (rc >= HTTP_ERR_SIZE) {
5428 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5429 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005430 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005431 free(err);
5432 }
5433 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005434 else if (!strcmp(args[0], "compression")) {
5435 struct comp *comp;
5436 if (curproxy->comp == NULL) {
5437 comp = calloc(1, sizeof(struct comp));
5438 curproxy->comp = comp;
5439 } else {
5440 comp = curproxy->comp;
5441 }
5442
5443 if (!strcmp(args[1], "algo")) {
5444 int cur_arg;
William Lallemand552df672012-11-07 13:21:47 +01005445 struct comp_ctx ctx;
5446
William Lallemand82fe75c2012-10-23 10:25:10 +02005447 cur_arg = 2;
5448 if (!*args[cur_arg]) {
5449 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5450 file, linenum, args[0]);
5451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
5454 while (*(args[cur_arg])) {
5455 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5456 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5457 file, linenum, args[0], args[cur_arg]);
5458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
5460 }
William Lallemand552df672012-11-07 13:21:47 +01005461 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5462 curproxy->comp->algos->end(&ctx);
5463 } else {
5464 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5465 file, linenum, args[0], args[cur_arg]);
5466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005469 cur_arg ++;
5470 continue;
5471 }
5472 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005473 else if (!strcmp(args[1], "offload")) {
5474 comp->offload = 1;
5475 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005476 else if (!strcmp(args[1], "type")) {
5477 int cur_arg;
5478 cur_arg = 2;
5479 if (!*args[cur_arg]) {
5480 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5481 file, linenum, args[0]);
5482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
5484 }
5485 while (*(args[cur_arg])) {
5486 comp_append_type(comp, args[cur_arg]);
5487 cur_arg ++;
5488 continue;
5489 }
5490 }
5491 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005492 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005493 file, linenum, args[0]);
5494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
5496 }
5497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005498 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005499 struct cfg_kw_list *kwl;
5500 int index;
5501
5502 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5503 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5504 if (kwl->kw[index].section != CFG_LISTEN)
5505 continue;
5506 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5507 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005508 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005509 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005510 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005511 err_code |= ERR_ALERT | ERR_FATAL;
5512 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005513 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005514 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005515 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005516 err_code |= ERR_WARN;
5517 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005518 }
Willy Tarreau93893792009-07-23 13:19:11 +02005519 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005520 }
5521 }
5522 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005523
Willy Tarreau6daf3432008-01-22 16:44:08 +01005524 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527 }
Willy Tarreau93893792009-07-23 13:19:11 +02005528 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005529 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005530 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531}
5532
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005533int
5534cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5535{
5536
5537 int err_code = 0;
5538 const char *err;
5539
5540 if (!strcmp(args[0], "userlist")) { /* new userlist */
5541 struct userlist *newul;
5542
5543 if (!*args[1]) {
5544 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5545 file, linenum, args[0]);
5546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
5548 }
5549
5550 err = invalid_char(args[1]);
5551 if (err) {
5552 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5553 file, linenum, *err, args[0], args[1]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
5557
5558 for (newul = userlist; newul; newul = newul->next)
5559 if (!strcmp(newul->name, args[1])) {
5560 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5561 file, linenum, args[1]);
5562 err_code |= ERR_WARN;
5563 goto out;
5564 }
5565
5566 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5567 if (!newul) {
5568 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5569 err_code |= ERR_ALERT | ERR_ABORT;
5570 goto out;
5571 }
5572
5573 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5574 newul->name = strdup(args[1]);
5575
5576 if (!newul->groupusers | !newul->name) {
5577 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5578 err_code |= ERR_ALERT | ERR_ABORT;
5579 goto out;
5580 }
5581
5582 newul->next = userlist;
5583 userlist = newul;
5584
5585 } else if (!strcmp(args[0], "group")) { /* new group */
5586 int cur_arg, i;
5587 const char *err;
5588
5589 if (!*args[1]) {
5590 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5591 file, linenum, args[0]);
5592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
5594 }
5595
5596 err = invalid_char(args[1]);
5597 if (err) {
5598 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5599 file, linenum, *err, args[0], args[1]);
5600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
5602 }
5603
5604 for(i = 0; i < userlist->grpcnt; i++)
5605 if (!strcmp(userlist->groups[i], args[1])) {
5606 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5607 file, linenum, args[1], userlist->name);
5608 err_code |= ERR_ALERT;
5609 goto out;
5610 }
5611
5612 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5613 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5614 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 }
5618
5619 cur_arg = 2;
5620
5621 while (*args[cur_arg]) {
5622 if (!strcmp(args[cur_arg], "users")) {
5623 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5624 cur_arg += 2;
5625 continue;
5626 } else {
5627 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5628 file, linenum, args[0]);
5629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
5631 }
5632 }
5633
5634 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5635 } else if (!strcmp(args[0], "user")) { /* new user */
5636 struct auth_users *newuser;
5637 int cur_arg;
5638
5639 if (!*args[1]) {
5640 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5641 file, linenum, args[0]);
5642 err_code |= ERR_ALERT | ERR_FATAL;
5643 goto out;
5644 }
5645
5646 for (newuser = userlist->users; newuser; newuser = newuser->next)
5647 if (!strcmp(newuser->user, args[1])) {
5648 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5649 file, linenum, args[1], userlist->name);
5650 err_code |= ERR_ALERT;
5651 goto out;
5652 }
5653
5654 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5655 if (!newuser) {
5656 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5657 err_code |= ERR_ALERT | ERR_ABORT;
5658 goto out;
5659 }
5660
5661 newuser->user = strdup(args[1]);
5662
5663 newuser->next = userlist->users;
5664 userlist->users = newuser;
5665
5666 cur_arg = 2;
5667
5668 while (*args[cur_arg]) {
5669 if (!strcmp(args[cur_arg], "password")) {
5670#ifndef CONFIG_HAP_CRYPT
5671 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5672 file, linenum);
5673 err_code |= ERR_ALERT;
5674#endif
5675 newuser->pass = strdup(args[cur_arg + 1]);
5676 cur_arg += 2;
5677 continue;
5678 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5679 newuser->pass = strdup(args[cur_arg + 1]);
5680 newuser->flags |= AU_O_INSECURE;
5681 cur_arg += 2;
5682 continue;
5683 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005684 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005685 cur_arg += 2;
5686 continue;
5687 } else {
5688 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5689 file, linenum, args[0]);
5690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
5692 }
5693 }
5694 } else {
5695 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5696 err_code |= ERR_ALERT | ERR_FATAL;
5697 }
5698
5699out:
5700 return err_code;
5701}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702
5703/*
5704 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005705 * Returns the error code, 0 if OK, or any combination of :
5706 * - ERR_ABORT: must abort ASAP
5707 * - ERR_FATAL: we can continue parsing but not start the service
5708 * - ERR_WARN: a warning has been emitted
5709 * - ERR_ALERT: an alert has been emitted
5710 * Only the two first ones can stop processing, the two others are just
5711 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005713int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005714{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005715 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 FILE *f;
5717 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005718 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005719 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720
Willy Tarreaubaaee002006-06-26 02:48:02 +02005721 if ((f=fopen(file,"r")) == NULL)
5722 return -1;
5723
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005724 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005725 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005726 char *end;
5727 char *args[MAX_LINE_ARGS + 1];
5728 char *line = thisline;
5729
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730 linenum++;
5731
5732 end = line + strlen(line);
5733
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005734 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5735 /* Check if we reached the limit and the last char is not \n.
5736 * Watch out for the last line without the terminating '\n'!
5737 */
5738 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005739 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005740 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005741 }
5742
Willy Tarreaubaaee002006-06-26 02:48:02 +02005743 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005744 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 line++;
5746
5747 arg = 0;
5748 args[arg] = line;
5749
5750 while (*line && arg < MAX_LINE_ARGS) {
5751 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5752 * C equivalent value. Other combinations left unchanged (eg: \1).
5753 */
5754 if (*line == '\\') {
5755 int skip = 0;
5756 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5757 *line = line[1];
5758 skip = 1;
5759 }
5760 else if (line[1] == 'r') {
5761 *line = '\r';
5762 skip = 1;
5763 }
5764 else if (line[1] == 'n') {
5765 *line = '\n';
5766 skip = 1;
5767 }
5768 else if (line[1] == 't') {
5769 *line = '\t';
5770 skip = 1;
5771 }
5772 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005773 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 unsigned char hex1, hex2;
5775 hex1 = toupper(line[2]) - '0';
5776 hex2 = toupper(line[3]) - '0';
5777 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5778 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5779 *line = (hex1<<4) + hex2;
5780 skip = 3;
5781 }
5782 else {
5783 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005784 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 }
5786 }
5787 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005788 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 end -= skip;
5790 }
5791 line++;
5792 }
5793 else if (*line == '#' || *line == '\n' || *line == '\r') {
5794 /* end of string, end of loop */
5795 *line = 0;
5796 break;
5797 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005798 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005800 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005801 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 line++;
5803 args[++arg] = line;
5804 }
5805 else {
5806 line++;
5807 }
5808 }
5809
5810 /* empty line */
5811 if (!**args)
5812 continue;
5813
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005814 if (*line) {
5815 /* we had to stop due to too many args.
5816 * Let's terminate the string, print the offending part then cut the
5817 * last arg.
5818 */
5819 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5820 line++;
5821 *line = '\0';
5822
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005823 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005824 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005825 err_code |= ERR_ALERT | ERR_FATAL;
5826 args[arg] = line;
5827 }
5828
Willy Tarreau540abe42007-05-02 20:50:16 +02005829 /* zero out remaining args and ensure that at least one entry
5830 * is zeroed out.
5831 */
5832 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 args[arg] = line;
5834 }
5835
Willy Tarreau3842f002009-06-14 11:39:52 +02005836 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005837 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005838 char *tmp;
5839
Willy Tarreau3842f002009-06-14 11:39:52 +02005840 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005841 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005842 for (arg=0; *args[arg+1]; arg++)
5843 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005844 *tmp = '\0'; // fix the next arg to \0
5845 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005846 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005847 else if (!strcmp(args[0], "default")) {
5848 kwm = KWM_DEF;
5849 for (arg=0; *args[arg+1]; arg++)
5850 args[arg] = args[arg+1]; // shift args after inversion
5851 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005852
William Lallemand0f99e342011-10-12 17:50:54 +02005853 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5854 strcmp(args[0], "log") != 0) {
5855 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005856 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005857 }
5858
Willy Tarreau977b8e42006-12-29 14:19:17 +01005859 if (!strcmp(args[0], "listen") ||
5860 !strcmp(args[0], "frontend") ||
5861 !strcmp(args[0], "backend") ||
5862 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005863 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005865 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005866 cursection = strdup(args[0]);
5867 }
5868 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005870 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005871 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005872 }
5873 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005874 confsect = CFG_USERLIST;
5875 free(cursection);
5876 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005877 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005878 else if (!strcmp(args[0], "peers")) {
5879 confsect = CFG_PEERS;
5880 free(cursection);
5881 cursection = strdup(args[0]);
5882 }
5883
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 /* else it's a section keyword */
5885
5886 switch (confsect) {
5887 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005888 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 break;
5890 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005891 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005893 case CFG_USERLIST:
5894 err_code |= cfg_parse_users(file, linenum, args, kwm);
5895 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005896 case CFG_PEERS:
5897 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5898 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005899 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005900 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005901 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005903
5904 if (err_code & ERR_ABORT)
5905 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005907 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005908 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005909 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005910 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005911}
5912
Willy Tarreaubb925012009-07-23 13:36:36 +02005913/*
5914 * Returns the error code, 0 if OK, or any combination of :
5915 * - ERR_ABORT: must abort ASAP
5916 * - ERR_FATAL: we can continue parsing but not start the service
5917 * - ERR_WARN: a warning has been emitted
5918 * - ERR_ALERT: an alert has been emitted
5919 * Only the two first ones can stop processing, the two others are just
5920 * indicators.
5921 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005922int check_config_validity()
5923{
5924 int cfgerr = 0;
5925 struct proxy *curproxy = NULL;
5926 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005927 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005928 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005929 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005930 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931
Willy Tarreau2a65ff02012-09-13 17:54:29 +02005932 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005933 /*
5934 * Now, check for the integrity of all that we have collected.
5935 */
5936
5937 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005938 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005939
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005940 /* first, we will invert the proxy list order */
5941 curproxy = NULL;
5942 while (proxy) {
5943 struct proxy *next;
5944
5945 next = proxy->next;
5946 proxy->next = curproxy;
5947 curproxy = proxy;
5948 if (!next)
5949 break;
5950 proxy = next;
5951 }
5952
Willy Tarreaubaaee002006-06-26 02:48:02 +02005953 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005954 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005955 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005956 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005957 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005958 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005959 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01005960 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005961
Willy Tarreau050536d2012-10-04 08:47:34 +02005962 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005963 /* proxy ID not set, use automatic numbering with first
5964 * spare entry starting with next_pxid.
5965 */
5966 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5967 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5968 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005969 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005970 next_pxid++;
5971
Willy Tarreau55ea7572007-06-17 19:56:27 +02005972
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005974 /* ensure we don't keep listeners uselessly bound */
5975 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976 curproxy = curproxy->next;
5977 continue;
5978 }
5979
Willy Tarreau16a21472012-11-19 12:39:59 +01005980 /* number of processes this proxy is bound to */
5981 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
5982
Willy Tarreauff01a212009-03-15 13:46:16 +01005983 switch (curproxy->mode) {
5984 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005985 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005986 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005987 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5988 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005989 cfgerr++;
5990 }
5991
5992 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005993 Warning("config : servers will be ignored for %s '%s'.\n",
5994 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005995 break;
5996
5997 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005998 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005999 break;
6000
6001 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02006002 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01006003 break;
6004 }
6005
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006006 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006007 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006008 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006009 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6010 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006011 cfgerr++;
6012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006013#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006014 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006015 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6016 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006017 cfgerr++;
6018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006020 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006021 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6022 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006023 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006024 }
6025 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006026 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006027 /* If no LB algo is set in a backend, and we're not in
6028 * transparent mode, dispatch mode nor proxy mode, we
6029 * want to use balance roundrobin by default.
6030 */
6031 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6032 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 }
6034 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006035
Willy Tarreau1620ec32011-08-06 17:05:02 +02006036 if (curproxy->options & PR_O_DISPATCH)
6037 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6038 else if (curproxy->options & PR_O_HTTP_PROXY)
6039 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6040 else if (curproxy->options & PR_O_TRANSP)
6041 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006042
Willy Tarreau1620ec32011-08-06 17:05:02 +02006043 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6044 if (curproxy->options & PR_O_DISABLE404) {
6045 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6046 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6047 err_code |= ERR_WARN;
6048 curproxy->options &= ~PR_O_DISABLE404;
6049 }
6050 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6051 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6052 "send-state", proxy_type_str(curproxy), curproxy->id);
6053 err_code |= ERR_WARN;
6054 curproxy->options &= ~PR_O2_CHK_SNDST;
6055 }
Willy Tarreauef781042010-01-27 11:53:01 +01006056 }
6057
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006058 /* if a default backend was specified, let's find it */
6059 if (curproxy->defbe.name) {
6060 struct proxy *target;
6061
Alex Williams96532db2009-11-01 21:27:13 -05006062 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006063 if (!target) {
6064 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6065 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006066 cfgerr++;
6067 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006068 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6069 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006070 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006071 } else {
6072 free(curproxy->defbe.name);
6073 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006074 /* we force the backend to be present on at least all of
6075 * the frontend's processes.
6076 */
6077 target->bind_proc = curproxy->bind_proc ?
6078 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006079
6080 /* Emit a warning if this proxy also has some servers */
6081 if (curproxy->srv) {
6082 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6083 curproxy->id);
6084 err_code |= ERR_WARN;
6085 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006086 }
6087 }
6088
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006089 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006090 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6091 /* map jump target for ACT_SETBE in req_rep chain */
6092 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006093 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006094 struct proxy *target;
6095
Willy Tarreaua496b602006-12-17 23:15:24 +01006096 if (exp->action != ACT_SETBE)
6097 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006098
Alex Williams96532db2009-11-01 21:27:13 -05006099 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006100 if (!target) {
6101 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6102 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006103 cfgerr++;
6104 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006105 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6106 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006107 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006108 } else {
6109 free((void *)exp->replace);
6110 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006111 /* we force the backend to be present on at least all of
6112 * the frontend's processes.
6113 */
6114 target->bind_proc = curproxy->bind_proc ?
6115 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006116 }
6117 }
6118 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006119
6120 /* find the target proxy for 'use_backend' rules */
6121 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006122 struct proxy *target;
6123
Alex Williams96532db2009-11-01 21:27:13 -05006124 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006125
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006126 if (!target) {
6127 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6128 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006129 cfgerr++;
6130 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006131 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6132 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006133 cfgerr++;
6134 } else {
6135 free((void *)rule->be.name);
6136 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006137 /* we force the backend to be present on at least all of
6138 * the frontend's processes.
6139 */
6140 target->bind_proc = curproxy->bind_proc ?
6141 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006142 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006143 }
6144
6145 /* find the target proxy for 'use_backend' rules */
6146 list_for_each_entry(srule, &curproxy->server_rules, list) {
6147 struct server *target = findserver(curproxy, srule->srv.name);
6148
6149 if (!target) {
6150 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6151 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6152 cfgerr++;
6153 continue;
6154 }
6155 free((void *)srule->srv.name);
6156 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006157 }
6158
Emeric Brunb982a3d2010-01-04 15:45:53 +01006159 /* find the target table for 'stick' rules */
6160 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6161 struct proxy *target;
6162
Emeric Brun1d33b292010-01-04 15:47:17 +01006163 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6164 if (mrule->flags & STK_IS_STORE)
6165 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6166
Emeric Brunb982a3d2010-01-04 15:45:53 +01006167 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006168 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006169 else
6170 target = curproxy;
6171
6172 if (!target) {
6173 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6174 curproxy->id, mrule->table.name);
6175 cfgerr++;
6176 }
6177 else if (target->table.size == 0) {
6178 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6179 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6180 cfgerr++;
6181 }
Willy Tarreau12785782012-04-27 21:37:17 +02006182 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6183 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006184 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6185 cfgerr++;
6186 }
6187 else {
6188 free((void *)mrule->table.name);
6189 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006190 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006191 }
6192 }
6193
6194 /* find the target table for 'store response' rules */
6195 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6196 struct proxy *target;
6197
Emeric Brun1d33b292010-01-04 15:47:17 +01006198 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6199
Emeric Brunb982a3d2010-01-04 15:45:53 +01006200 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006201 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006202 else
6203 target = curproxy;
6204
6205 if (!target) {
6206 Alert("Proxy '%s': unable to find store table '%s'.\n",
6207 curproxy->id, mrule->table.name);
6208 cfgerr++;
6209 }
6210 else if (target->table.size == 0) {
6211 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6212 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6213 cfgerr++;
6214 }
Willy Tarreau12785782012-04-27 21:37:17 +02006215 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6216 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006217 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6218 cfgerr++;
6219 }
6220 else {
6221 free((void *)mrule->table.name);
6222 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006223 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006224 }
6225 }
6226
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006227 /* find the target table for 'tcp-request' layer 4 rules */
6228 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6229 struct proxy *target;
6230
Willy Tarreau56123282010-08-06 19:06:56 +02006231 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006232 continue;
6233
6234 if (trule->act_prm.trk_ctr.table.n)
6235 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6236 else
6237 target = curproxy;
6238
6239 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006240 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6241 curproxy->id, trule->act_prm.trk_ctr.table.n,
6242 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006243 cfgerr++;
6244 }
6245 else if (target->table.size == 0) {
6246 Alert("Proxy '%s': table '%s' used but not configured.\n",
6247 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6248 cfgerr++;
6249 }
6250 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006251 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 +02006252 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6253 cfgerr++;
6254 }
6255 else {
6256 free(trule->act_prm.trk_ctr.table.n);
6257 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006258 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006259 * to pass a list of counters to track and allocate them right here using
6260 * stktable_alloc_data_type().
6261 */
6262 }
6263 }
6264
Willy Tarreaud1f96522010-08-03 19:34:32 +02006265 /* find the target table for 'tcp-request' layer 6 rules */
6266 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6267 struct proxy *target;
6268
Willy Tarreau56123282010-08-06 19:06:56 +02006269 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006270 continue;
6271
6272 if (trule->act_prm.trk_ctr.table.n)
6273 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6274 else
6275 target = curproxy;
6276
6277 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006278 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6279 curproxy->id, trule->act_prm.trk_ctr.table.n,
6280 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006281 cfgerr++;
6282 }
6283 else if (target->table.size == 0) {
6284 Alert("Proxy '%s': table '%s' used but not configured.\n",
6285 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6286 cfgerr++;
6287 }
6288 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006289 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 +02006290 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6291 cfgerr++;
6292 }
6293 else {
6294 free(trule->act_prm.trk_ctr.table.n);
6295 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006296 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006297 * to pass a list of counters to track and allocate them right here using
6298 * stktable_alloc_data_type().
6299 */
6300 }
6301 }
6302
Emeric Brun32da3c42010-09-23 18:39:19 +02006303 if (curproxy->table.peers.name) {
6304 struct peers *curpeers = peers;
6305
6306 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6307 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6308 free((void *)curproxy->table.peers.name);
6309 curproxy->table.peers.p = peers;
6310 break;
6311 }
6312 }
6313
6314 if (!curpeers) {
6315 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6316 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006317 free((void *)curproxy->table.peers.name);
6318 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006319 cfgerr++;
6320 }
6321 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006322 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6323 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006324 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006325 cfgerr++;
6326 }
6327 }
6328
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006329 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006330 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006331 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6332 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6333 "proxy", curproxy->id);
6334 cfgerr++;
6335 goto out_uri_auth_compat;
6336 }
6337
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006338 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006339 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006340 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006341 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006342
Willy Tarreau95fa4692010-02-01 13:05:50 +01006343 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6344 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006345
6346 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006347 uri_auth_compat_req[i++] = "realm";
6348 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6349 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006350
Willy Tarreau95fa4692010-02-01 13:05:50 +01006351 uri_auth_compat_req[i++] = "unless";
6352 uri_auth_compat_req[i++] = "{";
6353 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6354 uri_auth_compat_req[i++] = "}";
6355 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006356
Willy Tarreauff011f22011-01-06 17:51:27 +01006357 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6358 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006359 cfgerr++;
6360 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006361 }
6362
Willy Tarreauff011f22011-01-06 17:51:27 +01006363 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006364
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006365 if (curproxy->uri_auth->auth_realm) {
6366 free(curproxy->uri_auth->auth_realm);
6367 curproxy->uri_auth->auth_realm = NULL;
6368 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006369
6370 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006371 }
6372out_uri_auth_compat:
6373
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006374 cfgerr += acl_find_targets(curproxy);
6375
Willy Tarreau2738a142006-07-08 17:28:09 +02006376 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006377 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006378 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006379 (!curproxy->timeout.connect ||
6380 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006381 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006382 " | While not properly invalid, you will certainly encounter various problems\n"
6383 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006384 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006385 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006386 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006387 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006388
Willy Tarreau1fa31262007-12-03 00:36:16 +01006389 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6390 * We must still support older configurations, so let's find out whether those
6391 * parameters have been set or must be copied from contimeouts.
6392 */
6393 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006394 if (!curproxy->timeout.tarpit ||
6395 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006396 /* tarpit timeout not set. We search in the following order:
6397 * default.tarpit, curr.connect, default.connect.
6398 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006399 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006400 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006401 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006402 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006403 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006404 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006405 }
6406 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006407 (!curproxy->timeout.queue ||
6408 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006409 /* queue timeout not set. We search in the following order:
6410 * default.queue, curr.connect, default.connect.
6411 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006412 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006413 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006414 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006415 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006416 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006417 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006418 }
6419 }
6420
Willy Tarreau1620ec32011-08-06 17:05:02 +02006421 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006422 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6423 curproxy->check_req = (char *)malloc(curproxy->check_len);
6424 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006425 }
6426
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006427 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006428 if (curproxy->nb_req_cap) {
6429 if (curproxy->mode == PR_MODE_HTTP) {
6430 curproxy->req_cap_pool = create_pool("ptrcap",
6431 curproxy->nb_req_cap * sizeof(char *),
6432 MEM_F_SHARED);
6433 } else {
6434 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6435 proxy_type_str(curproxy), curproxy->id);
6436 err_code |= ERR_WARN;
6437 curproxy->to_log &= ~LW_REQHDR;
6438 curproxy->nb_req_cap = 0;
6439 }
6440 }
6441
6442 if (curproxy->nb_rsp_cap) {
6443 if (curproxy->mode == PR_MODE_HTTP) {
6444 curproxy->rsp_cap_pool = create_pool("ptrcap",
6445 curproxy->nb_rsp_cap * sizeof(char *),
6446 MEM_F_SHARED);
6447 } else {
6448 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6449 proxy_type_str(curproxy), curproxy->id);
6450 err_code |= ERR_WARN;
6451 curproxy->to_log &= ~LW_REQHDR;
6452 curproxy->nb_rsp_cap = 0;
6453 }
6454 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006455
Willy Tarreau196729e2012-05-31 19:30:26 +02006456 /* compile the log format */
Willy Tarreau99a7ca22012-05-31 19:39:23 +02006457 if (!(curproxy->cap & PR_CAP_FE)) {
6458 if (curproxy->logformat_string != default_http_log_format &&
6459 curproxy->logformat_string != default_tcp_log_format &&
6460 curproxy->logformat_string != clf_http_log_format)
6461 free(curproxy->logformat_string);
6462 curproxy->logformat_string = NULL;
6463 }
6464
Willy Tarreau196729e2012-05-31 19:30:26 +02006465 if (curproxy->logformat_string)
6466 parse_logformat_string(curproxy->logformat_string, curproxy, &curproxy->logformat, curproxy->mode);
6467
6468 if (curproxy->uniqueid_format_string)
6469 parse_logformat_string(curproxy->uniqueid_format_string, curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
6470
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 /* first, we will invert the servers list order */
6472 newsrv = NULL;
6473 while (curproxy->srv) {
6474 struct server *next;
6475
6476 next = curproxy->srv->next;
6477 curproxy->srv->next = newsrv;
6478 newsrv = curproxy->srv;
6479 if (!next)
6480 break;
6481 curproxy->srv = next;
6482 }
6483
Willy Tarreaudd701652010-05-25 23:03:02 +02006484 /* assign automatic UIDs to servers which don't have one yet */
6485 next_id = 1;
6486 newsrv = curproxy->srv;
6487 while (newsrv != NULL) {
6488 if (!newsrv->puid) {
6489 /* server ID not set, use automatic numbering with first
6490 * spare entry starting with next_svid.
6491 */
6492 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6493 newsrv->conf.id.key = newsrv->puid = next_id;
6494 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6495 }
6496 next_id++;
6497 newsrv = newsrv->next;
6498 }
6499
Willy Tarreau20697042007-11-15 23:26:18 +01006500 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006501 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502
Willy Tarreau62c3be22012-01-20 13:12:32 +01006503 /*
6504 * If this server supports a maxconn parameter, it needs a dedicated
6505 * tasks to fill the emptied slots when a connection leaves.
6506 * Also, resolve deferred tracking dependency if needed.
6507 */
6508 newsrv = curproxy->srv;
6509 while (newsrv != NULL) {
6510 if (newsrv->minconn > newsrv->maxconn) {
6511 /* Only 'minconn' was specified, or it was higher than or equal
6512 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6513 * this will avoid further useless expensive computations.
6514 */
6515 newsrv->maxconn = newsrv->minconn;
6516 } else if (newsrv->maxconn && !newsrv->minconn) {
6517 /* minconn was not specified, so we set it to maxconn */
6518 newsrv->minconn = newsrv->maxconn;
6519 }
6520
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006521#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006522 if (newsrv->use_ssl || newsrv->check.use_ssl)
6523 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006524#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006525
Willy Tarreau62c3be22012-01-20 13:12:32 +01006526 if (newsrv->trackit) {
6527 struct proxy *px;
6528 struct server *srv;
6529 char *pname, *sname;
6530
6531 pname = newsrv->trackit;
6532 sname = strrchr(pname, '/');
6533
6534 if (sname)
6535 *sname++ = '\0';
6536 else {
6537 sname = pname;
6538 pname = NULL;
6539 }
6540
6541 if (pname) {
6542 px = findproxy(pname, PR_CAP_BE);
6543 if (!px) {
6544 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6545 proxy_type_str(curproxy), curproxy->id,
6546 newsrv->id, pname);
6547 cfgerr++;
6548 goto next_srv;
6549 }
6550 } else
6551 px = curproxy;
6552
6553 srv = findserver(px, sname);
6554 if (!srv) {
6555 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6556 proxy_type_str(curproxy), curproxy->id,
6557 newsrv->id, sname);
6558 cfgerr++;
6559 goto next_srv;
6560 }
6561
6562 if (!(srv->state & SRV_CHECKED)) {
6563 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6564 "tracking as it does not have checks enabled.\n",
6565 proxy_type_str(curproxy), curproxy->id,
6566 newsrv->id, px->id, srv->id);
6567 cfgerr++;
6568 goto next_srv;
6569 }
6570
6571 if (curproxy != px &&
6572 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6573 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6574 "tracking: disable-on-404 option inconsistency.\n",
6575 proxy_type_str(curproxy), curproxy->id,
6576 newsrv->id, px->id, srv->id);
6577 cfgerr++;
6578 goto next_srv;
6579 }
6580
6581 /* if the other server is forced disabled, we have to do the same here */
6582 if (srv->state & SRV_MAINTAIN) {
6583 newsrv->state |= SRV_MAINTAIN;
6584 newsrv->state &= ~SRV_RUNNING;
6585 newsrv->health = 0;
6586 }
6587
6588 newsrv->track = srv;
6589 newsrv->tracknext = srv->tracknext;
6590 srv->tracknext = newsrv;
6591
6592 free(newsrv->trackit);
6593 newsrv->trackit = NULL;
6594 }
6595 next_srv:
6596 newsrv = newsrv->next;
6597 }
6598
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006599 /* We have to initialize the server lookup mechanism depending
6600 * on what LB algorithm was choosen.
6601 */
6602
6603 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6604 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6605 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006606 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6607 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6608 init_server_map(curproxy);
6609 } else {
6610 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6611 fwrr_init_server_groups(curproxy);
6612 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006613 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006614
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006615 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006616 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6617 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6618 fwlc_init_server_tree(curproxy);
6619 } else {
6620 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6621 fas_init_server_tree(curproxy);
6622 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006623 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006624
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006625 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006626 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6627 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6628 chash_init_server_tree(curproxy);
6629 } else {
6630 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6631 init_server_map(curproxy);
6632 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006633 break;
6634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006635
6636 if (curproxy->options & PR_O_LOGASAP)
6637 curproxy->to_log &= ~LW_BYTES;
6638
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006639 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006640 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006641 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6642 proxy_type_str(curproxy), curproxy->id);
6643 err_code |= ERR_WARN;
6644 }
6645
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006646 if (curproxy->mode != PR_MODE_HTTP) {
6647 int optnum;
6648
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006649 if (curproxy->uri_auth) {
6650 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6651 proxy_type_str(curproxy), curproxy->id);
6652 err_code |= ERR_WARN;
6653 curproxy->uri_auth = NULL;
6654 }
6655
Willy Tarreau87cf5142011-08-19 22:57:24 +02006656 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006657 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6658 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6659 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006660 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006661 }
6662
6663 if (curproxy->options & PR_O_ORGTO) {
6664 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6665 "originalto", proxy_type_str(curproxy), curproxy->id);
6666 err_code |= ERR_WARN;
6667 curproxy->options &= ~PR_O_ORGTO;
6668 }
6669
6670 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6671 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6672 (curproxy->cap & cfg_opts[optnum].cap) &&
6673 (curproxy->options & cfg_opts[optnum].val)) {
6674 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6675 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6676 err_code |= ERR_WARN;
6677 curproxy->options &= ~cfg_opts[optnum].val;
6678 }
6679 }
6680
6681 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6682 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6683 (curproxy->cap & cfg_opts2[optnum].cap) &&
6684 (curproxy->options2 & cfg_opts2[optnum].val)) {
6685 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6686 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6687 err_code |= ERR_WARN;
6688 curproxy->options2 &= ~cfg_opts2[optnum].val;
6689 }
6690 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006691
Willy Tarreauefa5f512010-03-30 20:13:29 +02006692#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006693 if (curproxy->bind_hdr_occ) {
6694 curproxy->bind_hdr_occ = 0;
6695 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6696 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6697 err_code |= ERR_WARN;
6698 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006699#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006700 }
6701
Willy Tarreaubaaee002006-06-26 02:48:02 +02006702 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006703 * ensure that we're not cross-dressing a TCP server into HTTP.
6704 */
6705 newsrv = curproxy->srv;
6706 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006707 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006708 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6709 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006710 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006711 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006712
Willy Tarreau0cec3312011-10-31 13:49:26 +01006713 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6714 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6715 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6716 err_code |= ERR_WARN;
6717 }
6718
Willy Tarreauefa5f512010-03-30 20:13:29 +02006719#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006720 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6721 newsrv->bind_hdr_occ = 0;
6722 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6723 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6724 err_code |= ERR_WARN;
6725 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006726#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006727 newsrv = newsrv->next;
6728 }
6729
Willy Tarreauc1a21672009-08-16 22:37:44 +02006730 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02006731 if (!curproxy->accept)
6732 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006733
Willy Tarreauc1a21672009-08-16 22:37:44 +02006734 if (curproxy->tcp_req.inspect_delay ||
6735 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006736 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006737
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006738 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006739 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006740 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006741 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006742
6743 /* both TCP and HTTP must check switching rules */
6744 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6745 }
6746
6747 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006748 if (curproxy->tcp_req.inspect_delay ||
6749 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6750 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6751
Emeric Brun97679e72010-09-23 17:56:44 +02006752 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6753 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6754
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006755 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006756 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006757 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006758 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006759
6760 /* If the backend does requires RDP cookie persistence, we have to
6761 * enable the corresponding analyser.
6762 */
6763 if (curproxy->options2 & PR_O2_RDPC_PRST)
6764 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6765 }
6766
Emeric Brunc52962f2012-11-15 18:28:02 +01006767#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006768 /* Configure SSL for each bind line.
6769 * Note: if configuration fails at some point, the ->ctx member
6770 * remains NULL so that listeners can later detach.
6771 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006772 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01006773 if (!bind_conf->is_ssl) {
6774 if (bind_conf->default_ctx) {
6775 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
6776 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6777 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006778 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01006779 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006780 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02006781 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006782 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006783 cfgerr++;
6784 continue;
6785 }
6786
Emeric Brun4b3091e2012-09-24 15:48:52 +02006787 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006788 Alert("Unable to allocate SSL session cache.\n");
6789 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006790 continue;
6791 }
6792
Emeric Brunfc0421f2012-09-07 17:30:07 +02006793 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006794 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006795 }
Emeric Brunc52962f2012-11-15 18:28:02 +01006796#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006797
Willy Tarreaue6b98942007-10-29 01:09:36 +01006798 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006799 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02006800 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006801 if (!listener->luid) {
6802 /* listener ID not set, use automatic numbering with first
6803 * spare entry starting with next_luid.
6804 */
6805 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6806 listener->conf.id.key = listener->luid = next_id;
6807 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006808 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006809 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006810
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006811 /* enable separate counters */
6812 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6813 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01006814 if (!listener->name)
6815 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006816 }
Willy Tarreau81796be2012-09-22 19:11:47 +02006817
Willy Tarreaue6b98942007-10-29 01:09:36 +01006818 if (curproxy->options & PR_O_TCP_NOLING)
6819 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02006820 if (!listener->maxconn)
6821 listener->maxconn = curproxy->maxconn;
6822 if (!listener->backlog)
6823 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01006824 if (!listener->maxaccept)
6825 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
6826
6827 /* we want to have an optimal behaviour on single process mode to
6828 * maximize the work at once, but in multi-process we want to keep
6829 * some fairness between processes, so we target half of the max
6830 * number of events to be balanced over all the processes the proxy
6831 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
6832 * used to disable the limit.
6833 */
6834 if (listener->maxaccept > 0) {
6835 if (nbproc > 1)
6836 listener->maxaccept = (listener->maxaccept + 1) / 2;
6837 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
6838 }
6839
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006840 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006841 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006842 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006843 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006844
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006845 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6846 listener->options |= LI_O_TCP_RULES;
6847
Willy Tarreaude3041d2010-05-31 10:56:17 +02006848 if (curproxy->mon_mask.s_addr)
6849 listener->options |= LI_O_CHK_MONNET;
6850
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006851 /* smart accept mode is automatic in HTTP mode */
6852 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006853 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006854 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6855 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006856 }
6857
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006858 /* Release unused SSL configs */
6859 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6860 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006861 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006862#ifdef USE_OPENSSL
6863 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006864 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006865 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02006866 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02006867 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006868#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006869 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02006870
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006871 /* Check multi-process mode compatibility for the current proxy */
6872 if (global.nbproc > 1) {
6873 int nbproc = 0;
6874 if (curproxy->bind_proc) {
6875 int proc;
6876 for (proc = 0; proc < global.nbproc; proc++) {
6877 if (curproxy->bind_proc & (1 << proc)) {
6878 nbproc++;
6879 }
6880 }
6881 } else {
6882 nbproc = global.nbproc;
6883 }
6884 if (curproxy->table.peers.name) {
6885 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6886 curproxy->id);
6887 cfgerr++;
6888 }
6889 if (nbproc > 1) {
6890 if (curproxy->uri_auth) {
6891 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6892 curproxy->id);
6893 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6894 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6895 curproxy->id);
6896 }
6897 }
6898 if (curproxy->appsession_name) {
6899 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6900 curproxy->id);
6901 }
6902 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6903 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6904 curproxy->id);
6905 }
6906 }
6907 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006908
6909 /* create the task associated with the proxy */
6910 curproxy->task = task_new();
6911 if (curproxy->task) {
6912 curproxy->task->context = curproxy;
6913 curproxy->task->process = manage_proxy;
6914 /* no need to queue, it will be done automatically if some
6915 * listener gets limited.
6916 */
6917 curproxy->task->expire = TICK_ETERNITY;
6918 } else {
6919 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6920 curproxy->id);
6921 cfgerr++;
6922 }
6923
Willy Tarreaubaaee002006-06-26 02:48:02 +02006924 curproxy = curproxy->next;
6925 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006926
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006927 /* Check multi-process mode compatibility */
6928 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02006929 if (global.stats_fe && !global.stats_fe->bind_proc) {
6930 Warning("stats socket will not work as expected in multi-process mode (nbproc > 1), you should force process binding using 'stats bind-process'.\n");
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006931 }
6932 }
6933
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006934 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6935 struct auth_users *curuser;
6936 int g;
6937
6938 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6939 unsigned int group_mask = 0;
6940 char *group = NULL;
6941
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006942 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006943 continue;
6944
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006945 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006946
6947 for (g = 0; g < curuserlist->grpcnt; g++)
6948 if (!strcmp(curuserlist->groups[g], group))
6949 break;
6950
6951 if (g == curuserlist->grpcnt) {
6952 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6953 curuserlist->name, group, curuser->user);
6954 err_code |= ERR_ALERT | ERR_FATAL;
6955 goto out;
6956 }
6957
6958 group_mask |= (1 << g);
6959 }
6960
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006961 free(curuser->u.groups);
6962 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006963 }
6964
6965 for (g = 0; g < curuserlist->grpcnt; g++) {
6966 char *user = NULL;
6967
6968 if (!curuserlist->groupusers[g])
6969 continue;
6970
6971 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6972 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6973 if (!strcmp(curuser->user, user))
6974 break;
6975
6976 if (!curuser) {
6977 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6978 curuserlist->name, user, curuserlist->groups[g]);
6979 err_code |= ERR_ALERT | ERR_FATAL;
6980 goto out;
6981 }
6982
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006983 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006984 }
6985
6986 free(curuserlist->groupusers[g]);
6987 }
6988
6989 free(curuserlist->groupusers);
6990
6991#ifdef DEBUG_AUTH
6992 for (g = 0; g < curuserlist->grpcnt; g++) {
6993 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6994
6995 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02006996 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006997 fprintf(stderr, " %s", curuser->user);
6998 }
6999
7000 fprintf(stderr, "\n");
7001 }
7002#endif
7003
Willy Tarreaufbb78422011-06-05 15:38:35 +02007004 }
7005
7006 /* automatically compute fullconn if not set. We must not do it in the
7007 * loop above because cross-references are not yet fully resolved.
7008 */
7009 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7010 /* If <fullconn> is not set, let's set it to 10% of the sum of
7011 * the possible incoming frontend's maxconns.
7012 */
7013 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7014 struct proxy *fe;
7015 int total = 0;
7016
7017 /* sum up the number of maxconns of frontends which
7018 * reference this backend at least once or which are
7019 * the same one ('listen').
7020 */
7021 for (fe = proxy; fe; fe = fe->next) {
7022 struct switching_rule *rule;
7023 struct hdr_exp *exp;
7024 int found = 0;
7025
7026 if (!(fe->cap & PR_CAP_FE))
7027 continue;
7028
7029 if (fe == curproxy) /* we're on a "listen" instance */
7030 found = 1;
7031
7032 if (fe->defbe.be == curproxy) /* "default_backend" */
7033 found = 1;
7034
7035 /* check if a "use_backend" rule matches */
7036 if (!found) {
7037 list_for_each_entry(rule, &fe->switching_rules, list) {
7038 if (rule->be.backend == curproxy) {
7039 found = 1;
7040 break;
7041 }
7042 }
7043 }
7044
7045 /* check if a "reqsetbe" rule matches */
7046 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7047 if (exp->action == ACT_SETBE &&
7048 (struct proxy *)exp->replace == curproxy) {
7049 found = 1;
7050 break;
7051 }
7052 }
7053
7054 /* now we've checked all possible ways to reference a backend
7055 * from a frontend.
7056 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007057 if (!found)
7058 continue;
7059 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007060 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007061 /* we have the sum of the maxconns in <total>. We only
7062 * keep 10% of that sum to set the default fullconn, with
7063 * a hard minimum of 1 (to avoid a divide by zero).
7064 */
7065 curproxy->fullconn = (total + 9) / 10;
7066 if (!curproxy->fullconn)
7067 curproxy->fullconn = 1;
7068 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007069 }
7070
Willy Tarreau056f5682010-06-06 15:51:11 +02007071 /* initialize stick-tables on backend capable proxies. This must not
7072 * be done earlier because the data size may be discovered while parsing
7073 * other proxies.
7074 */
7075 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02007076 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02007077
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007078 /*
7079 * Recount currently required checks.
7080 */
7081
7082 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7083 int optnum;
7084
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007085 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7086 if (curproxy->options & cfg_opts[optnum].val)
7087 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007088
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007089 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7090 if (curproxy->options2 & cfg_opts2[optnum].val)
7091 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007092 }
7093
Willy Tarreau122541c2011-09-07 21:24:49 +02007094 if (peers) {
7095 struct peers *curpeers = peers, **last;
7096 struct peer *p, *pb;
7097
7098 /* Remove all peers sections which don't have a valid listener.
7099 * This can happen when a peers section is never referenced and
7100 * does not contain a local peer.
7101 */
7102 last = &peers;
7103 while (*last) {
7104 curpeers = *last;
7105 if (curpeers->peers_fe) {
7106 last = &curpeers->next;
7107 continue;
7108 }
7109
7110 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7111 curpeers->id, localpeer);
7112
7113 p = curpeers->remote;
7114 while (p) {
7115 pb = p->next;
7116 free(p->id);
7117 free(p);
7118 p = pb;
7119 }
7120
7121 /* Destroy and unlink this curpeers section.
7122 * Note: curpeers is backed up into *last.
7123 */
7124 free(curpeers->id);
7125 curpeers = curpeers->next;
7126 free(*last);
7127 *last = curpeers;
7128 }
7129 }
7130
Willy Tarreauac1932d2011-10-24 19:14:41 +02007131 if (!global.tune.max_http_hdr)
7132 global.tune.max_http_hdr = MAX_HTTP_HDR;
7133
Willy Tarreau34eb6712011-10-24 18:15:04 +02007134 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007135 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007136 MEM_F_SHARED);
7137
Willy Tarreaubb925012009-07-23 13:36:36 +02007138 if (cfgerr > 0)
7139 err_code |= ERR_ALERT | ERR_FATAL;
7140 out:
7141 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007142}
7143
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007144/*
7145 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7146 * parsing sessions.
7147 */
7148void cfg_register_keywords(struct cfg_kw_list *kwl)
7149{
7150 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7151}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007152
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007153/*
7154 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7155 */
7156void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7157{
7158 LIST_DEL(&kwl->list);
7159 LIST_INIT(&kwl->list);
7160}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007161
7162/*
7163 * Local variables:
7164 * c-indent-level: 8
7165 * c-basic-offset: 8
7166 * End:
7167 */