blob: 864a9fb9babf1d9c371e55811c5983e808f3fe89 [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 },
Willy Tarreau16bfb022010-01-16 19:48:41 +0100135 { "http-keep-alive", PR_O_KEEPALIVE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100137 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
139 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
140 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
141 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
142 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100143#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100145#else
146 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100147#endif
148
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150};
151
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152/* proxy->options2 */
153static const struct cfg_opt cfg_opts2[] =
154{
155#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
158 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100159#else
160 { "splice-request", 0, 0, 0, 0 },
161 { "splice-response", 0, 0, 0, 0 },
162 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100163#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
165 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
166 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
167 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
168 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
169 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
171 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
172 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400173 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200175 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200176 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100177 { NULL, 0, 0, 0 }
178};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179
Willy Tarreau6daf3432008-01-22 16:44:08 +0100180static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
182int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100183int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200185/* List head of all known configuration keywords */
186static struct cfg_kw_list cfg_keywords = {
187 .list = LIST_HEAD_INIT(cfg_keywords.list)
188};
189
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190/*
191 * converts <str> to a list of listeners which are dynamically allocated.
192 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
193 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
194 * - <port> is a numerical port from 1 to 65535 ;
195 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
196 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
198 * not NULL, it must be a valid pointer to either NULL or a freeable area that
199 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200201int 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 +0200202{
203 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100204 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 int port, end;
206
207 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200208
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100210 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100211 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212
213 str = next;
214 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100215 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 *next++ = 0;
217 }
218
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100219 ss2 = str2sa_range(str, &port, &end, err,
220 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
221 if (!ss2)
222 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100224 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100225 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200226 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100230 if (!port || !end) {
231 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
232 goto fail;
233 }
234
Emeric Bruned760922010-10-22 17:59:25 +0200235 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200236 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200237 goto fail;
238 }
239
240 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200241 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200242 goto fail;
243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100245 else if (ss2->ss_family == AF_UNSPEC) {
246 socklen_t addr_len;
247
248 /* We want to attach to an already bound fd whose number
249 * is in the addr part of ss2 when cast to sockaddr_in.
250 * Note that by definition there is a single listener.
251 * We still have to determine the address family to
252 * register the correct protocol.
253 */
254 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
255 addr_len = sizeof(*ss2);
256 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
257 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
258 goto fail;
259 }
260
261 port = end = get_host_port(ss2);
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100264 /* OK the address looks correct */
265 ss = *ss2;
266
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 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
Willy Tarreau40aa0702013-03-10 23:51:38 +0100275 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 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 Tarreaua91d0a52013-03-25 08:12:18 +0100418/* Report it if a request ACL condition uses some keywords that are incompatible
419 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
420 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
421 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100422 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100423static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100424{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100425 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200426 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100427
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100428 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100429 return 0;
430
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100431 acl = acl_cond_conflicts(cond, where);
432 if (acl) {
433 if (acl->name && *acl->name)
434 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
435 file, line, acl->name, sample_ckp_names(where));
436 else
437 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200438 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100439 return ERR_WARN;
440 }
441 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100442 return 0;
443
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100444 if (acl->name && *acl->name)
445 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200446 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100447 else
448 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200449 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100450 return ERR_WARN;
451}
452
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 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100594 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.ssl_max_record = atol(args[1]);
601 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200602#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200603 else if (!strcmp(args[0], "tune.bufsize")) {
604 if (*(args[1]) == 0) {
605 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
606 err_code |= ERR_ALERT | ERR_FATAL;
607 goto out;
608 }
609 global.tune.bufsize = atol(args[1]);
610 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
611 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100612 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100613 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200614 }
615 else if (!strcmp(args[0], "tune.maxrewrite")) {
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.tune.maxrewrite = atol(args[1]);
622 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
623 global.tune.maxrewrite = global.tune.bufsize / 2;
624 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100625 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
626 if (global.tune.client_rcvbuf != 0) {
627 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT;
629 goto out;
630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
635 }
636 global.tune.client_rcvbuf = atol(args[1]);
637 }
638 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
639 if (global.tune.server_rcvbuf != 0) {
640 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT;
642 goto out;
643 }
644 if (*(args[1]) == 0) {
645 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
646 err_code |= ERR_ALERT | ERR_FATAL;
647 goto out;
648 }
649 global.tune.server_rcvbuf = atol(args[1]);
650 }
651 else if (!strcmp(args[0], "tune.sndbuf.client")) {
652 if (global.tune.client_sndbuf != 0) {
653 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT;
655 goto out;
656 }
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 global.tune.client_sndbuf = atol(args[1]);
663 }
664 else if (!strcmp(args[0], "tune.sndbuf.server")) {
665 if (global.tune.server_sndbuf != 0) {
666 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT;
668 goto out;
669 }
670 if (*(args[1]) == 0) {
671 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675 global.tune.server_sndbuf = atol(args[1]);
676 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200677 else if (!strcmp(args[0], "tune.pipesize")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.pipesize = atol(args[1]);
684 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100685 else if (!strcmp(args[0], "tune.http.cookielen")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.cookie_len = atol(args[1]) + 1;
692 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200693 else if (!strcmp(args[0], "tune.http.maxhdr")) {
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
698 }
699 global.tune.max_http_hdr = atol(args[1]);
700 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100701 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
702#ifdef USE_ZLIB
703 if (*args[1]) {
704 global.tune.zlibmemlevel = atoi(args[1]);
705 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
706 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711 } else {
712 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
713 file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717#else
718 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721#endif
722 }
723 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
724#ifdef USE_ZLIB
725 if (*args[1]) {
726 global.tune.zlibwindowsize = atoi(args[1]);
727 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
728 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
729 file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 } else {
734 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
735 file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739#else
740 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743#endif
744 }
William Lallemandf3747832012-11-09 12:33:10 +0100745 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
746 if (*args[1]) {
747 global.tune.comp_maxlevel = atoi(args[1]);
748 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
749 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
750 file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 } else {
755 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761 else if (!strcmp(args[0], "uid")) {
762 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200763 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200764 err_code |= ERR_ALERT;
765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 }
767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772 global.uid = atol(args[1]);
773 }
774 else if (!strcmp(args[0], "gid")) {
775 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200776 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200777 err_code |= ERR_ALERT;
778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 }
780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 global.gid = atol(args[1]);
786 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200787 /* user/group name handling */
788 else if (!strcmp(args[0], "user")) {
789 struct passwd *ha_user;
790 if (global.uid != 0) {
791 Alert("parsing [%s:%d] : user/uid 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_user = getpwnam(args[1]);
797 if (ha_user != NULL) {
798 global.uid = (int)ha_user->pw_uid;
799 }
800 else {
801 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 +0200802 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200803 }
804 }
805 else if (!strcmp(args[0], "group")) {
806 struct group *ha_group;
807 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200808 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT;
810 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200811 }
812 errno = 0;
813 ha_group = getgrnam(args[1]);
814 if (ha_group != NULL) {
815 global.gid = (int)ha_group->gr_gid;
816 }
817 else {
818 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 +0200819 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200820 }
821 }
822 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 if (*(args[1]) == 0) {
825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200826 err_code |= ERR_ALERT | ERR_FATAL;
827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 }
829 global.nbproc = atol(args[1]);
830 }
831 else if (!strcmp(args[0], "maxconn")) {
832 if (global.maxconn != 0) {
833 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200834 err_code |= ERR_ALERT;
835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 }
837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 }
842 global.maxconn = atol(args[1]);
843#ifdef SYSTEM_MAXCONN
844 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
845 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);
846 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 }
849#endif /* SYSTEM_MAXCONN */
850 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200851 else if (!strcmp(args[0], "maxsslconn")) {
852#ifdef USE_OPENSSL
853 if (*(args[1]) == 0) {
854 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858 global.maxsslconn = atol(args[1]);
859#else
Emeric Brun0914df82012-10-02 18:45:42 +0200860 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200863#endif
864 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200865 else if (!strcmp(args[0], "maxconnrate")) {
866 if (global.cps_lim != 0) {
867 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT;
869 goto out;
870 }
871 if (*(args[1]) == 0) {
872 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
875 }
876 global.cps_lim = atol(args[1]);
877 }
William Lallemandd85f9172012-11-09 17:05:39 +0100878 else if (!strcmp(args[0], "maxcomprate")) {
879 if (*(args[1]) == 0) {
880 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT | ERR_FATAL;
882 goto out;
883 }
884 global.comp_rate_lim = atoi(args[1]) * 1024;
885 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100886 else if (!strcmp(args[0], "maxpipes")) {
887 if (global.maxpipes != 0) {
888 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200889 err_code |= ERR_ALERT;
890 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100891 }
892 if (*(args[1]) == 0) {
893 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200894 err_code |= ERR_ALERT | ERR_FATAL;
895 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100896 }
897 global.maxpipes = atol(args[1]);
898 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100899 else if (!strcmp(args[0], "maxzlibmem")) {
900 if (*(args[1]) == 0) {
901 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
William Lallemande3a7d992012-11-20 11:25:20 +0100905 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100906 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100907 else if (!strcmp(args[0], "maxcompcpuusage")) {
908 if (*(args[1]) == 0) {
909 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
910 err_code |= ERR_ALERT | ERR_FATAL;
911 goto out;
912 }
913 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100914 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100915 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
918 }
919}
920
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 else if (!strcmp(args[0], "ulimit-n")) {
922 if (global.rlimit_nofile != 0) {
923 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT;
925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927 if (*(args[1]) == 0) {
928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932 global.rlimit_nofile = atol(args[1]);
933 }
934 else if (!strcmp(args[0], "chroot")) {
935 if (global.chroot != NULL) {
936 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200937 err_code |= ERR_ALERT;
938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 }
940 if (*(args[1]) == 0) {
941 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 }
945 global.chroot = strdup(args[1]);
946 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200947 else if (!strcmp(args[0], "description")) {
948 int i, len=0;
949 char *d;
950
951 if (!*args[1]) {
952 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
953 file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957
958 for(i=1; *args[i]; i++)
959 len += strlen(args[i])+1;
960
961 if (global.desc)
962 free(global.desc);
963
964 global.desc = d = (char *)calloc(1, len);
965
966 d += sprintf(d, "%s", args[1]);
967 for(i=2; *args[i]; i++)
968 d += sprintf(d, " %s", args[i]);
969 }
970 else if (!strcmp(args[0], "node")) {
971 int i;
972 char c;
973
974 for (i=0; args[1][i]; i++) {
975 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100976 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
977 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200978 break;
979 }
980
981 if (!i || args[1][i]) {
982 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
983 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
984 file, linenum, args[0]);
985 err_code |= ERR_ALERT | ERR_FATAL;
986 goto out;
987 }
988
989 if (global.node)
990 free(global.node);
991
992 global.node = strdup(args[1]);
993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200994 else if (!strcmp(args[0], "pidfile")) {
995 if (global.pidfile != NULL) {
996 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200997 err_code |= ERR_ALERT;
998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200999 }
1000 if (*(args[1]) == 0) {
1001 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 }
1005 global.pidfile = strdup(args[1]);
1006 }
Emeric Bruned760922010-10-22 17:59:25 +02001007 else if (!strcmp(args[0], "unix-bind")) {
1008 int cur_arg = 1;
1009 while (*(args[cur_arg])) {
1010 if (!strcmp(args[cur_arg], "prefix")) {
1011 if (global.unix_bind.prefix != NULL) {
1012 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1013 err_code |= ERR_ALERT;
1014 cur_arg += 2;
1015 continue;
1016 }
1017
1018 if (*(args[cur_arg+1]) == 0) {
1019 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1024 cur_arg += 2;
1025 continue;
1026 }
1027
1028 if (!strcmp(args[cur_arg], "mode")) {
1029
1030 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1031 cur_arg += 2;
1032 continue;
1033 }
1034
1035 if (!strcmp(args[cur_arg], "uid")) {
1036
1037 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1038 cur_arg += 2;
1039 continue;
1040 }
1041
1042 if (!strcmp(args[cur_arg], "gid")) {
1043
1044 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1045 cur_arg += 2;
1046 continue;
1047 }
1048
1049 if (!strcmp(args[cur_arg], "user")) {
1050 struct passwd *user;
1051
1052 user = getpwnam(args[cur_arg + 1]);
1053 if (!user) {
1054 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1055 file, linenum, args[0], args[cur_arg + 1 ]);
1056 err_code |= ERR_ALERT | ERR_FATAL;
1057 goto out;
1058 }
1059
1060 global.unix_bind.ux.uid = user->pw_uid;
1061 cur_arg += 2;
1062 continue;
1063 }
1064
1065 if (!strcmp(args[cur_arg], "group")) {
1066 struct group *group;
1067
1068 group = getgrnam(args[cur_arg + 1]);
1069 if (!group) {
1070 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1071 file, linenum, args[0], args[cur_arg + 1 ]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075
1076 global.unix_bind.ux.gid = group->gr_gid;
1077 cur_arg += 2;
1078 continue;
1079 }
1080
Willy Tarreaub48f9582011-09-05 01:17:06 +02001081 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001082 file, linenum, args[0]);
1083 err_code |= ERR_ALERT | ERR_FATAL;
1084 goto out;
1085 }
1086 }
William Lallemand0f99e342011-10-12 17:50:54 +02001087 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1088 /* delete previous herited or defined syslog servers */
1089 struct logsrv *back;
1090 struct logsrv *tmp;
1091
1092 if (*(args[1]) != 0) {
1093 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097
1098 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1099 LIST_DEL(&tmp->list);
1100 free(tmp);
1101 }
1102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001104 struct sockaddr_storage *sk;
1105 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001106 struct logsrv *logsrv;
1107
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 if (*(args[1]) == 0 || *(args[2]) == 0) {
1109 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001112 }
William Lallemand0f99e342011-10-12 17:50:54 +02001113
1114 logsrv = calloc(1, sizeof(struct logsrv));
1115
1116 logsrv->facility = get_log_facility(args[2]);
1117 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001118 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001119 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001120 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 }
1122
William Lallemand0f99e342011-10-12 17:50:54 +02001123 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001125 logsrv->level = get_log_level(args[3]);
1126 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001129 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 }
1132
William Lallemand0f99e342011-10-12 17:50:54 +02001133 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001134 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001135 logsrv->minlvl = get_log_level(args[4]);
1136 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001137 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001138 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001139 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001140 }
1141 }
1142
Willy Tarreau902636f2013-03-10 19:44:48 +01001143 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001144 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001145 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001146 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001147 free(logsrv);
1148 goto out;
1149 }
1150 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001151
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001152 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001153 if (port1 != port2) {
1154 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1155 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001156 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001157 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001158 goto out;
1159 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001160
William Lallemand0f99e342011-10-12 17:50:54 +02001161 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001162 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001163 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001164 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165
William Lallemand0f99e342011-10-12 17:50:54 +02001166 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001167 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001168 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1169 char *name;
1170 int len;
1171
1172 if (global.log_send_hostname != NULL) {
1173 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1174 err_code |= ERR_ALERT;
1175 goto out;
1176 }
1177
1178 if (*(args[1]))
1179 name = args[1];
1180 else
1181 name = hostname;
1182
1183 len = strlen(name);
1184
1185 /* We'll add a space after the name to respect the log format */
1186 free(global.log_send_hostname);
1187 global.log_send_hostname = malloc(len + 2);
1188 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1189 }
Kevinm48936af2010-12-22 16:08:21 +00001190 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1191 if (*(args[1]) == 0) {
1192 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
1196 free(global.log_tag);
1197 global.log_tag = strdup(args[1]);
1198 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001199 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1200 if (global.spread_checks != 0) {
1201 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001202 err_code |= ERR_ALERT;
1203 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001204 }
1205 if (*(args[1]) == 0) {
1206 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001209 }
1210 global.spread_checks = atol(args[1]);
1211 if (global.spread_checks < 0 || global.spread_checks > 50) {
1212 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001213 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001214 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001216 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1217#ifdef USE_CPU_AFFINITY
1218 int cur_arg, i;
1219 unsigned int proc = 0;
1220 unsigned long cpus = 0;
1221
1222 if (strcmp(args[1], "all") == 0)
1223 proc = 0xFFFFFFFF;
1224 else if (strcmp(args[1], "odd") == 0)
1225 proc = 0x55555555;
1226 else if (strcmp(args[1], "even") == 0)
1227 proc = 0xAAAAAAAA;
1228 else {
1229 proc = atoi(args[1]);
1230 if (proc >= 1 && proc <= 32)
1231 proc = 1 << (proc - 1);
1232 }
1233
1234 if (!proc || !*args[2]) {
1235 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",
1236 file, linenum, args[0]);
1237 err_code |= ERR_ALERT | ERR_FATAL;
1238 goto out;
1239 }
1240
1241 cur_arg = 2;
1242 while (*args[cur_arg]) {
1243 unsigned int low, high;
1244
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001245 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001246 char *dash = strchr(args[cur_arg], '-');
1247
1248 low = high = str2uic(args[cur_arg]);
1249 if (dash)
1250 high = str2uic(dash + 1);
1251
1252 if (high < low) {
1253 unsigned int swap = low;
1254 low = high;
1255 high = swap;
1256 }
1257
1258 if (low < 0 || high >= sizeof(long) * 8) {
1259 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1260 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
1263 }
1264
1265 while (low <= high)
1266 cpus |= 1UL << low++;
1267 }
1268 else {
1269 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1270 file, linenum, args[0], args[cur_arg]);
1271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
1273 }
1274 cur_arg++;
1275 }
1276 for (i = 0; i < 32; i++)
1277 if (proc & (1 << i))
1278 global.cpu_map[i] = cpus;
1279#else
1280 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283#endif
1284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001285 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001286 struct cfg_kw_list *kwl;
1287 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001288 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001289
1290 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1291 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1292 if (kwl->kw[index].section != CFG_GLOBAL)
1293 continue;
1294 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001295 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001296 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001297 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001298 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001299 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001300 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001301 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001302 err_code |= ERR_WARN;
1303 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001304 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001305 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001306 }
1307 }
1308 }
1309
Willy Tarreaubaaee002006-06-26 02:48:02 +02001310 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001311 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001313
Willy Tarreau058e9072009-07-20 09:30:05 +02001314 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001315 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001316 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001317}
1318
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001319void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001320{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001321 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 defproxy.mode = PR_MODE_TCP;
1323 defproxy.state = PR_STNEW;
1324 defproxy.maxconn = cfg_maxpconn;
1325 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001326
Simon Horman66183002013-02-23 10:16:43 +09001327 defproxy.defsrv.check.inter = DEF_CHKINTR;
1328 defproxy.defsrv.check.fastinter = 0;
1329 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001330 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1331 defproxy.defsrv.agent.fastinter = 0;
1332 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001333 defproxy.defsrv.check.rise = DEF_RISETIME;
1334 defproxy.defsrv.check.fall = DEF_FALLTIME;
1335 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1336 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001337 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001338 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001339 defproxy.defsrv.maxqueue = 0;
1340 defproxy.defsrv.minconn = 0;
1341 defproxy.defsrv.maxconn = 0;
1342 defproxy.defsrv.slowstart = 0;
1343 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1344 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1345 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346}
1347
Willy Tarreauade5ec42010-01-28 19:33:49 +01001348
1349static int create_cond_regex_rule(const char *file, int line,
1350 struct proxy *px, int dir, int action, int flags,
1351 const char *cmd, const char *reg, const char *repl,
1352 const char **cond_start)
1353{
1354 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001355 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001356 const char *err;
1357 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001358 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001359
1360 if (px == &defproxy) {
1361 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto err;
1364 }
1365
1366 if (*reg == 0) {
1367 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto err;
1370 }
1371
1372 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1373 err_code |= ERR_WARN;
1374
Willy Tarreau5321c422010-01-28 20:35:13 +01001375 if (cond_start &&
1376 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001377 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1378 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1379 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001380 err_code |= ERR_ALERT | ERR_FATAL;
1381 goto err;
1382 }
1383 }
1384 else if (cond_start && **cond_start) {
1385 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1386 file, line, cmd, *cond_start);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto err;
1389 }
1390
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001391 err_code |= warnif_cond_conflicts(cond,
1392 (dir == SMP_OPT_DIR_REQ) ?
1393 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1394 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1395 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001396
Willy Tarreauade5ec42010-01-28 19:33:49 +01001397 preg = calloc(1, sizeof(regex_t));
1398 if (!preg) {
1399 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1400 err_code = ERR_ALERT | ERR_FATAL;
1401 goto err;
1402 }
1403
1404 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1405 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1406 err_code = ERR_ALERT | ERR_FATAL;
1407 goto err;
1408 }
1409
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001410 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001411 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001412 if (repl && err) {
1413 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1414 file, line, cmd, *err);
1415 err_code |= ERR_ALERT | ERR_FATAL;
1416 goto err;
1417 }
1418
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001419 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001420 err_code |= ERR_WARN;
1421
Willy Tarreauf4068b62012-05-08 17:37:49 +02001422 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001423 return err_code;
1424 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001425 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001426 free(preg);
1427 return err_code;
1428}
1429
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001431 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001432 * Returns the error code, 0 if OK, or any combination of :
1433 * - ERR_ABORT: must abort ASAP
1434 * - ERR_FATAL: we can continue parsing but not start the service
1435 * - ERR_WARN: a warning has been emitted
1436 * - ERR_ALERT: an alert has been emitted
1437 * Only the two first ones can stop processing, the two others are just
1438 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001440int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1441{
1442 static struct peers *curpeers = NULL;
1443 struct peer *newpeer = NULL;
1444 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001445 struct bind_conf *bind_conf;
1446 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001447 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001448 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001449
1450 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001451 if (!*args[1]) {
1452 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto out;
1455 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001456
1457 err = invalid_char(args[1]);
1458 if (err) {
1459 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1460 file, linenum, *err, args[0], args[1]);
1461 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001462 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001463 }
1464
1465 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1466 /*
1467 * If there are two proxies with the same name only following
1468 * combinations are allowed:
1469 */
1470 if (strcmp(curpeers->id, args[1]) == 0) {
1471 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1472 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1473 err_code |= ERR_WARN;
1474 }
1475 }
1476
1477 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1478 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1479 err_code |= ERR_ALERT | ERR_ABORT;
1480 goto out;
1481 }
1482
1483 curpeers->next = peers;
1484 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001485 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001486 curpeers->conf.line = linenum;
1487 curpeers->last_change = now.tv_sec;
1488 curpeers->id = strdup(args[1]);
1489 }
1490 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001491 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001492 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001493 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001494
1495 if (!*args[2]) {
1496 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1497 file, linenum, args[0]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 err = invalid_char(args[1]);
1503 if (err) {
1504 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1505 file, linenum, *err, args[1]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1511 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1512 err_code |= ERR_ALERT | ERR_ABORT;
1513 goto out;
1514 }
1515
1516 /* the peers are linked backwards first */
1517 curpeers->count++;
1518 newpeer->next = curpeers->remote;
1519 curpeers->remote = newpeer;
1520 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001521 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001522 newpeer->conf.line = linenum;
1523
1524 newpeer->last_change = now.tv_sec;
1525 newpeer->id = strdup(args[1]);
1526
Willy Tarreau902636f2013-03-10 19:44:48 +01001527 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001528 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001529 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001532 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001533
1534 proto = protocol_by_family(sk->ss_family);
1535 if (!proto || !proto->connect) {
1536 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1537 file, linenum, args[0], args[1]);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001541
1542 if (port1 != port2) {
1543 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1544 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 }
1548
Willy Tarreau2aa38802013-02-20 19:20:59 +01001549 if (!port1) {
1550 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1551 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001552 err_code |= ERR_ALERT | ERR_FATAL;
1553 goto out;
1554 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001555
Emeric Brun32da3c42010-09-23 18:39:19 +02001556 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001557 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001558 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001559 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001560
Emeric Brun32da3c42010-09-23 18:39:19 +02001561 if (strcmp(newpeer->id, localpeer) == 0) {
1562 /* Current is local peer, it define a frontend */
1563 newpeer->local = 1;
1564
1565 if (!curpeers->peers_fe) {
1566 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1567 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1568 err_code |= ERR_ALERT | ERR_ABORT;
1569 goto out;
1570 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001571
Willy Tarreau237250c2011-07-29 01:49:03 +02001572 init_new_proxy(curpeers->peers_fe);
1573 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001574
1575 curpeers->peers_fe->last_change = now.tv_sec;
1576 curpeers->peers_fe->id = strdup(args[1]);
1577 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001578 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001579 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1580 curpeers->peers_fe->timeout.connect = 5000;
1581 curpeers->peers_fe->accept = peer_accept;
1582 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001583 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1584 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001585
1586 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1587
Willy Tarreau902636f2013-03-10 19:44:48 +01001588 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1589 if (errmsg && *errmsg) {
1590 indent_msg(&errmsg, 2);
1591 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001592 }
1593 else
1594 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1595 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001596 err_code |= ERR_FATAL;
1597 goto out;
1598 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001599
1600 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1601 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1602 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1603 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1604 l->accept = session_accept;
1605 l->handler = process_session;
1606 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1607 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1608 global.maxsock += l->maxconn;
1609 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001610 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001611 else {
1612 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1613 file, linenum, args[0], args[1],
1614 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1615 err_code |= ERR_FATAL;
1616 goto out;
1617 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001618 }
1619 } /* neither "peer" nor "peers" */
1620 else if (*args[0] != 0) {
1621 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1622 err_code |= ERR_ALERT | ERR_FATAL;
1623 goto out;
1624 }
1625
1626out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001627 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001628 return err_code;
1629}
1630
Simon Horman69d29f92013-02-23 15:14:19 +09001631static int init_check(struct check *check, int type, const char * file, int linenum)
1632{
1633 check->type = type;
1634
1635 /* Allocate buffer for requests... */
1636 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1637 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1638 return ERR_ALERT | ERR_ABORT;
1639 }
1640 check->bi->size = global.tune.chksize;
1641
1642 /* Allocate buffer for responses... */
1643 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1644 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1645 return ERR_ALERT | ERR_ABORT;
1646 }
1647 check->bo->size = global.tune.chksize;
1648
1649 /* Allocate buffer for partial results... */
1650 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1651 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1652 return ERR_ALERT | ERR_ABORT;
1653 }
1654
1655 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1656
1657 return 0;
1658}
Emeric Brun32da3c42010-09-23 18:39:19 +02001659
Willy Tarreau3842f002009-06-14 11:39:52 +02001660int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661{
1662 static struct proxy *curproxy = NULL;
1663 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001664 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001665 int rc;
1666 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001667 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001668 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001669 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001670 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001671 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001672
Willy Tarreau977b8e42006-12-29 14:19:17 +01001673 if (!strcmp(args[0], "listen"))
1674 rc = PR_CAP_LISTEN;
1675 else if (!strcmp(args[0], "frontend"))
1676 rc = PR_CAP_FE | PR_CAP_RS;
1677 else if (!strcmp(args[0], "backend"))
1678 rc = PR_CAP_BE | PR_CAP_RS;
1679 else if (!strcmp(args[0], "ruleset"))
1680 rc = PR_CAP_RS;
1681 else
1682 rc = PR_CAP_NONE;
1683
1684 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001685 if (!*args[1]) {
1686 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1687 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1688 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001689 err_code |= ERR_ALERT | ERR_ABORT;
1690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001692
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001693 err = invalid_char(args[1]);
1694 if (err) {
1695 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1696 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001697 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001698 }
1699
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001700 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1701 /*
1702 * If there are two proxies with the same name only following
1703 * combinations are allowed:
1704 *
1705 * listen backend frontend ruleset
1706 * listen - - - -
1707 * backend - - OK -
1708 * frontend - OK - -
1709 * ruleset - - - -
1710 */
1711
1712 if (!strcmp(curproxy->id, args[1]) &&
1713 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1714 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001715 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1716 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1717 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001718 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001719 }
1720 }
1721
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1723 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001724 err_code |= ERR_ALERT | ERR_ABORT;
1725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001727
Willy Tarreau97cb7802010-01-03 20:23:58 +01001728 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 curproxy->next = proxy;
1730 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001731 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1732 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001733 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001735 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736
1737 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001738 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001739 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001740
Willy Tarreau4348fad2012-09-20 16:48:07 +02001741 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1742
Willy Tarreau902636f2013-03-10 19:44:48 +01001743 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1744 if (errmsg && *errmsg) {
1745 indent_msg(&errmsg, 2);
1746 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001747 }
1748 else
1749 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1750 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001751 err_code |= ERR_FATAL;
1752 goto out;
1753 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001754
Willy Tarreau4348fad2012-09-20 16:48:07 +02001755 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001756 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001758 }
1759
1760 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001761 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001762 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001763
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001766 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001767 curproxy->no_options = defproxy.no_options;
1768 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001769 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001770 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001771 curproxy->except_net = defproxy.except_net;
1772 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001773 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001774 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001776 if (defproxy.fwdfor_hdr_len) {
1777 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1778 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1779 }
1780
Willy Tarreaub86db342009-11-30 11:50:16 +01001781 if (defproxy.orgto_hdr_len) {
1782 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1783 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1784 }
1785
Mark Lamourinec2247f02012-01-04 13:02:01 -05001786 if (defproxy.server_id_hdr_len) {
1787 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1788 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1789 }
1790
Willy Tarreau977b8e42006-12-29 14:19:17 +01001791 if (curproxy->cap & PR_CAP_FE) {
1792 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001793 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001794 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001795
1796 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001797 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1798 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001799
1800 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802
Willy Tarreau977b8e42006-12-29 14:19:17 +01001803 if (curproxy->cap & PR_CAP_BE) {
1804 curproxy->fullconn = defproxy.fullconn;
1805 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001807 if (defproxy.check_req) {
1808 curproxy->check_req = calloc(1, defproxy.check_len);
1809 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1810 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001811 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001813 if (defproxy.expect_str) {
1814 curproxy->expect_str = strdup(defproxy.expect_str);
1815 if (defproxy.expect_regex) {
1816 /* note: this regex is known to be valid */
1817 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1818 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1819 }
1820 }
1821
Willy Tarreau67402132012-05-31 20:40:20 +02001822 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001823 if (defproxy.cookie_name)
1824 curproxy->cookie_name = strdup(defproxy.cookie_name);
1825 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001826 if (defproxy.cookie_domain)
1827 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001828
Willy Tarreau31936852010-10-06 16:59:56 +02001829 if (defproxy.cookie_maxidle)
1830 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1831
1832 if (defproxy.cookie_maxlife)
1833 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1834
Emeric Brun647caf12009-06-30 17:57:00 +02001835 if (defproxy.rdp_cookie_name)
1836 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1837 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1838
Willy Tarreau01732802007-11-01 22:48:15 +01001839 if (defproxy.url_param_name)
1840 curproxy->url_param_name = strdup(defproxy.url_param_name);
1841 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001842
Benoitaffb4812009-03-25 13:02:10 +01001843 if (defproxy.hh_name)
1844 curproxy->hh_name = strdup(defproxy.hh_name);
1845 curproxy->hh_len = defproxy.hh_len;
1846 curproxy->hh_match_domain = defproxy.hh_match_domain;
1847
Willy Tarreauef9a3602012-12-08 22:29:20 +01001848 if (defproxy.conn_src.iface_name)
1849 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1850 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001851 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001852#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001853 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001854#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001855 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001856
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001857 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001858 if (defproxy.capture_name)
1859 curproxy->capture_name = strdup(defproxy.capture_name);
1860 curproxy->capture_namelen = defproxy.capture_namelen;
1861 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001863
Willy Tarreau977b8e42006-12-29 14:19:17 +01001864 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001865 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001866 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001867 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001868 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001869 curproxy->uri_auth = defproxy.uri_auth;
1870 curproxy->mon_net = defproxy.mon_net;
1871 curproxy->mon_mask = defproxy.mon_mask;
1872 if (defproxy.monitor_uri)
1873 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1874 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001875 if (defproxy.defbe.name)
1876 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001877
1878 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001879 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1880 if (curproxy->conf.logformat_string &&
1881 curproxy->conf.logformat_string != default_http_log_format &&
1882 curproxy->conf.logformat_string != default_tcp_log_format &&
1883 curproxy->conf.logformat_string != clf_http_log_format)
1884 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1885
1886 if (defproxy.conf.lfs_file) {
1887 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1888 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1889 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890 }
1891
1892 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001893 curproxy->timeout.connect = defproxy.timeout.connect;
1894 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001895 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001896 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001897 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001898 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001899 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001900 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001901 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 }
1903
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001905
1906 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001907 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001908 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001909 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001910 LIST_INIT(&node->list);
1911 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1912 }
1913
Willy Tarreau62a61232013-04-12 18:13:46 +02001914 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1915 if (curproxy->conf.uniqueid_format_string)
1916 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1917
1918 if (defproxy.conf.uif_file) {
1919 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1920 curproxy->conf.uif_line = defproxy.conf.uif_line;
1921 }
William Lallemanda73203e2012-03-12 12:48:57 +01001922
1923 /* copy default header unique id */
1924 if (defproxy.header_unique_id)
1925 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1926
William Lallemand82fe75c2012-10-23 10:25:10 +02001927 /* default compression options */
1928 if (defproxy.comp != NULL) {
1929 curproxy->comp = calloc(1, sizeof(struct comp));
1930 curproxy->comp->algos = defproxy.comp->algos;
1931 curproxy->comp->types = defproxy.comp->types;
1932 }
1933
Willy Tarreaubaaee002006-06-26 02:48:02 +02001934 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001935 curproxy->conf.used_listener_id = EB_ROOT;
1936 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001937
Willy Tarreau93893792009-07-23 13:19:11 +02001938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 }
1940 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1941 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001942 /* FIXME-20070101: we should do this too at the end of the
1943 * config parsing to free all default values.
1944 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001945 free(defproxy.check_req);
1946 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001947 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001948 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001949 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001950 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001951 free(defproxy.capture_name);
1952 free(defproxy.monitor_uri);
1953 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001954 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001955 free(defproxy.fwdfor_hdr_name);
1956 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001957 free(defproxy.orgto_hdr_name);
1958 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001959 free(defproxy.server_id_hdr_name);
1960 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001961 free(defproxy.expect_str);
1962 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001963
Willy Tarreau62a61232013-04-12 18:13:46 +02001964 if (defproxy.conf.logformat_string != default_http_log_format &&
1965 defproxy.conf.logformat_string != default_tcp_log_format &&
1966 defproxy.conf.logformat_string != clf_http_log_format)
1967 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001968
Willy Tarreau62a61232013-04-12 18:13:46 +02001969 free(defproxy.conf.uniqueid_format_string);
1970 free(defproxy.conf.lfs_file);
1971 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001972
Willy Tarreaua534fea2008-08-03 12:19:50 +02001973 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001974 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001975
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 /* we cannot free uri_auth because it might already be used */
1977 init_default_instance();
1978 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001979 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1980 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001981 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001982 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 }
1984 else if (curproxy == NULL) {
1985 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001986 err_code |= ERR_ALERT | ERR_FATAL;
1987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001989
1990 /* update the current file and line being parsed */
1991 curproxy->conf.args.file = curproxy->conf.file;
1992 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001993
1994 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001996 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001997 int cur_arg;
1998
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 if (curproxy == &defproxy) {
2000 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002003 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002004 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002005 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002006
Willy Tarreau24709282013-03-10 21:32:12 +01002007 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002008 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002013
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002014 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002015
2016 /* use default settings for unix sockets */
2017 bind_conf->ux.uid = global.unix_bind.ux.uid;
2018 bind_conf->ux.gid = global.unix_bind.ux.gid;
2019 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002020
2021 /* NOTE: the following line might create several listeners if there
2022 * are comma-separated IPs or port ranges. So all further processing
2023 * will have to be applied to all listeners created after last_listen.
2024 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002025 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2026 if (errmsg && *errmsg) {
2027 indent_msg(&errmsg, 2);
2028 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002029 }
2030 else
2031 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2032 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_ALERT | ERR_FATAL;
2034 goto out;
2035 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002036
Willy Tarreau4348fad2012-09-20 16:48:07 +02002037 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2038 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002039 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002040 }
2041
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002042 cur_arg = 2;
2043 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002044 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002045 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002046 char *err;
2047
Willy Tarreau26982662012-09-12 23:17:10 +02002048 kw = bind_find_kw(args[cur_arg]);
2049 if (kw) {
2050 char *err = NULL;
2051 int code;
2052
2053 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002054 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2055 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002056 cur_arg += 1 + kw->skip ;
2057 err_code |= ERR_ALERT | ERR_FATAL;
2058 goto out;
2059 }
2060
Willy Tarreau4348fad2012-09-20 16:48:07 +02002061 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002062 err_code |= code;
2063
2064 if (code) {
2065 if (err && *err) {
2066 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002067 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002068 }
2069 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002070 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2071 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002072 if (code & ERR_FATAL) {
2073 free(err);
2074 cur_arg += 1 + kw->skip;
2075 goto out;
2076 }
2077 }
2078 free(err);
2079 cur_arg += 1 + kw->skip;
2080 continue;
2081 }
2082
Willy Tarreau8638f482012-09-18 18:01:17 +02002083 err = NULL;
2084 if (!bind_dumped) {
2085 bind_dump_kws(&err);
2086 indent_msg(&err, 4);
2087 bind_dumped = 1;
2088 }
2089
2090 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2091 file, linenum, args[0], args[1], args[cur_arg],
2092 err ? " Registered keywords :" : "", err ? err : "");
2093 free(err);
2094
Willy Tarreau93893792009-07-23 13:19:11 +02002095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002097 }
Willy Tarreau93893792009-07-23 13:19:11 +02002098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 }
2100 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2101 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2102 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002107 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002108 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 /* flush useless bits */
2111 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002113 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002114 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002116 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002117
Willy Tarreau1c47f852006-07-09 08:22:27 +02002118 if (!*args[1]) {
2119 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2120 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002123 }
2124
Willy Tarreaua534fea2008-08-03 12:19:50 +02002125 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002126 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002127 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002128 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002129 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2130
Willy Tarreau93893792009-07-23 13:19:11 +02002131 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2134 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2135 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2136 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2137 else {
2138 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002139 err_code |= ERR_ALERT | ERR_FATAL;
2140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 }
2142 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002143 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002144 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002145
2146 if (curproxy == &defproxy) {
2147 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2148 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002149 err_code |= ERR_ALERT | ERR_FATAL;
2150 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002151 }
2152
2153 if (!*args[1]) {
2154 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002156 err_code |= ERR_ALERT | ERR_FATAL;
2157 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002158 }
2159
2160 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002161 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002162
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002163 if (curproxy->uuid <= 0) {
2164 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002165 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002168 }
2169
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002170 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2171 if (node) {
2172 struct proxy *target = container_of(node, struct proxy, conf.id);
2173 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2174 file, linenum, proxy_type_str(curproxy), curproxy->id,
2175 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2176 err_code |= ERR_ALERT | ERR_FATAL;
2177 goto out;
2178 }
2179 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002180 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002181 else if (!strcmp(args[0], "description")) {
2182 int i, len=0;
2183 char *d;
2184
Cyril Bonté99ed3272010-01-24 23:29:44 +01002185 if (curproxy == &defproxy) {
2186 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2187 file, linenum, args[0]);
2188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
2190 }
2191
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002192 if (!*args[1]) {
2193 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2194 file, linenum, args[0]);
2195 return -1;
2196 }
2197
2198 for(i=1; *args[i]; i++)
2199 len += strlen(args[i])+1;
2200
2201 d = (char *)calloc(1, len);
2202 curproxy->desc = d;
2203
2204 d += sprintf(d, "%s", args[1]);
2205 for(i=2; *args[i]; i++)
2206 d += sprintf(d, " %s", args[i]);
2207
2208 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002209 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2210 curproxy->state = PR_STSTOPPED;
2211 }
2212 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2213 curproxy->state = PR_STNEW;
2214 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002215 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2216 int cur_arg = 1;
2217 unsigned int set = 0;
2218
2219 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002220 unsigned int low, high;
2221
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002222 if (strcmp(args[cur_arg], "all") == 0) {
2223 set = 0;
2224 break;
2225 }
2226 else if (strcmp(args[cur_arg], "odd") == 0) {
2227 set |= 0x55555555;
2228 }
2229 else if (strcmp(args[cur_arg], "even") == 0) {
2230 set |= 0xAAAAAAAA;
2231 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002232 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002233 char *dash = strchr(args[cur_arg], '-');
2234
2235 low = high = str2uic(args[cur_arg]);
2236 if (dash)
2237 high = str2uic(dash + 1);
2238
2239 if (high < low) {
2240 unsigned int swap = low;
2241 low = high;
2242 high = swap;
2243 }
2244
2245 if (low < 1 || high > 32) {
2246 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002247 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002250 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002251
2252 if (high > global.nbproc) {
2253 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2254 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002255 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002256 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002257 while (low <= high)
2258 set |= 1 << (low++ - 1);
2259 }
2260 else {
2261 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2262 file, linenum, args[0]);
2263 err_code |= ERR_ALERT | ERR_FATAL;
2264 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002265 }
2266 cur_arg++;
2267 }
2268 curproxy->bind_proc = set;
2269 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002270 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002271 if (curproxy == &defproxy) {
2272 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002275 }
2276
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002277 err = invalid_char(args[1]);
2278 if (err) {
2279 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2280 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002282 }
2283
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002284 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002285 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2286 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002287 err_code |= ERR_ALERT | ERR_FATAL;
2288 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002289 }
2290 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2292 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293
Willy Tarreau977b8e42006-12-29 14:19:17 +01002294 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002295 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002296
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 if (*(args[1]) == 0) {
2298 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2299 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002303
Willy Tarreau67402132012-05-31 20:40:20 +02002304 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002305 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002306 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002307 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308 curproxy->cookie_name = strdup(args[1]);
2309 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002310
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 cur_arg = 2;
2312 while (*(args[cur_arg])) {
2313 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002314 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 }
2316 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002317 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 }
2319 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002320 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002321 }
2322 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002323 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002324 }
2325 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002326 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002327 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002328 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002329 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002332 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002334 else if (!strcmp(args[cur_arg], "httponly")) {
2335 curproxy->ck_opts |= PR_CK_HTTPONLY;
2336 }
2337 else if (!strcmp(args[cur_arg], "secure")) {
2338 curproxy->ck_opts |= PR_CK_SECURE;
2339 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002340 else if (!strcmp(args[cur_arg], "domain")) {
2341 if (!*args[cur_arg + 1]) {
2342 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2343 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002346 }
2347
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002348 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002349 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002350 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2351 " dots nor does not start with a dot."
2352 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002353 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002354 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002355 }
2356
2357 err = invalid_domainchar(args[cur_arg + 1]);
2358 if (err) {
2359 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2360 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002363 }
2364
Willy Tarreau68a897b2009-12-03 23:28:34 +01002365 if (!curproxy->cookie_domain) {
2366 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2367 } else {
2368 /* one domain was already specified, add another one by
2369 * building the string which will be returned along with
2370 * the cookie.
2371 */
2372 char *new_ptr;
2373 int new_len = strlen(curproxy->cookie_domain) +
2374 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2375 new_ptr = malloc(new_len);
2376 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2377 free(curproxy->cookie_domain);
2378 curproxy->cookie_domain = new_ptr;
2379 }
Willy Tarreau31936852010-10-06 16:59:56 +02002380 cur_arg++;
2381 }
2382 else if (!strcmp(args[cur_arg], "maxidle")) {
2383 unsigned int maxidle;
2384 const char *res;
2385
2386 if (!*args[cur_arg + 1]) {
2387 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2388 file, linenum, args[cur_arg]);
2389 err_code |= ERR_ALERT | ERR_FATAL;
2390 goto out;
2391 }
2392
2393 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2394 if (res) {
2395 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2396 file, linenum, *res, args[cur_arg]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
2400 curproxy->cookie_maxidle = maxidle;
2401 cur_arg++;
2402 }
2403 else if (!strcmp(args[cur_arg], "maxlife")) {
2404 unsigned int maxlife;
2405 const char *res;
2406
2407 if (!*args[cur_arg + 1]) {
2408 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2409 file, linenum, args[cur_arg]);
2410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
2412 }
2413
2414 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2415 if (res) {
2416 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2417 file, linenum, *res, args[cur_arg]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002422 cur_arg++;
2423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002425 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 +02002426 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
2430 cur_arg++;
2431 }
Willy Tarreau67402132012-05-31 20:40:20 +02002432 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2434 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436 }
2437
Willy Tarreau67402132012-05-31 20:40:20 +02002438 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2440 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002441 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002442 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002443
Willy Tarreau67402132012-05-31 20:40:20 +02002444 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002445 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2446 file, linenum);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002450 else if (!strcmp(args[0], "persist")) { /* persist */
2451 if (*(args[1]) == 0) {
2452 Alert("parsing [%s:%d] : missing persist method.\n",
2453 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002456 }
2457
2458 if (!strncmp(args[1], "rdp-cookie", 10)) {
2459 curproxy->options2 |= PR_O2_RDPC_PRST;
2460
Emeric Brunb982a3d2010-01-04 15:45:53 +01002461 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002462 const char *beg, *end;
2463
2464 beg = args[1] + 11;
2465 end = strchr(beg, ')');
2466
2467 if (!end || end == beg) {
2468 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2469 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002470 err_code |= ERR_ALERT | ERR_FATAL;
2471 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002472 }
2473
2474 free(curproxy->rdp_cookie_name);
2475 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2476 curproxy->rdp_cookie_len = end-beg;
2477 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002478 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002479 free(curproxy->rdp_cookie_name);
2480 curproxy->rdp_cookie_name = strdup("msts");
2481 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2482 }
2483 else { /* syntax */
2484 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2485 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002486 err_code |= ERR_ALERT | ERR_FATAL;
2487 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002488 }
2489 }
2490 else {
2491 Alert("parsing [%s:%d] : unknown persist method.\n",
2492 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002495 }
2496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002498 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002500 if (curproxy == &defproxy) {
2501 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2502 err_code |= ERR_ALERT | ERR_FATAL;
2503 goto out;
2504 }
2505
Willy Tarreau977b8e42006-12-29 14:19:17 +01002506 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002507 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002508
Willy Tarreaubaaee002006-06-26 02:48:02 +02002509 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002510 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 }
2515 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002516 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 curproxy->appsession_name = strdup(args[1]);
2518 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2519 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002520 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2521 if (err) {
2522 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2523 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002526 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002527 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002528
Willy Tarreau51041c72007-09-09 21:56:53 +02002529 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2530 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_ABORT;
2532 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002534
2535 cur_arg = 6;
2536 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002537 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2538 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002539 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002540 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002541 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002542 } else if (!strcmp(args[cur_arg], "prefix")) {
2543 curproxy->options2 |= PR_O2_AS_PFX;
2544 } else if (!strcmp(args[cur_arg], "mode")) {
2545 if (!*args[cur_arg + 1]) {
2546 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2547 file, linenum, args[0], args[cur_arg]);
2548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
2550 }
2551
2552 cur_arg++;
2553 if (!strcmp(args[cur_arg], "query-string")) {
2554 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2555 curproxy->options2 |= PR_O2_AS_M_QS;
2556 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2557 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2558 curproxy->options2 |= PR_O2_AS_M_PP;
2559 } else {
2560 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
2563 }
2564 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002565 cur_arg++;
2566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 } /* Url App Session */
2568 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002573 if (curproxy == &defproxy) {
2574 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
2577 }
2578
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 if (*(args[4]) == 0) {
2580 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2581 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002582 err_code |= ERR_ALERT | ERR_FATAL;
2583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002585 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 curproxy->capture_name = strdup(args[2]);
2587 curproxy->capture_namelen = strlen(curproxy->capture_name);
2588 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 curproxy->to_log |= LW_COOKIE;
2590 }
2591 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2592 struct cap_hdr *hdr;
2593
2594 if (curproxy == &defproxy) {
2595 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 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
2599
2600 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2601 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2602 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 }
2606
2607 hdr = calloc(sizeof(struct cap_hdr), 1);
2608 hdr->next = curproxy->req_cap;
2609 hdr->name = strdup(args[3]);
2610 hdr->namelen = strlen(args[3]);
2611 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002612 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 hdr->index = curproxy->nb_req_cap++;
2614 curproxy->req_cap = hdr;
2615 curproxy->to_log |= LW_REQHDR;
2616 }
2617 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2618 struct cap_hdr *hdr;
2619
2620 if (curproxy == &defproxy) {
2621 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 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 }
2625
2626 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2627 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2628 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 }
2632 hdr = calloc(sizeof(struct cap_hdr), 1);
2633 hdr->next = curproxy->rsp_cap;
2634 hdr->name = strdup(args[3]);
2635 hdr->namelen = strlen(args[3]);
2636 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002637 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002638 hdr->index = curproxy->nb_rsp_cap++;
2639 curproxy->rsp_cap = hdr;
2640 curproxy->to_log |= LW_RSPHDR;
2641 }
2642 else {
2643 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002645 err_code |= ERR_ALERT | ERR_FATAL;
2646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002647 }
2648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002650 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002651 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002652
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 if (*(args[1]) == 0) {
2654 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2655 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 }
2659 curproxy->conn_retries = atol(args[1]);
2660 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002661 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002662 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002663
2664 if (curproxy == &defproxy) {
2665 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2666 err_code |= ERR_ALERT | ERR_FATAL;
2667 goto out;
2668 }
2669
Willy Tarreau20b0de52012-12-24 15:45:22 +01002670 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2671 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2672 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2673 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002674 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002675 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2676 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002677 file, linenum, args[0]);
2678 err_code |= ERR_WARN;
2679 }
2680
Willy Tarreauff011f22011-01-06 17:51:27 +01002681 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002682
Willy Tarreauff011f22011-01-06 17:51:27 +01002683 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002684 err_code |= ERR_ALERT | ERR_ABORT;
2685 goto out;
2686 }
2687
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002688 err_code |= warnif_cond_conflicts(rule->cond,
2689 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2690 file, linenum);
2691
Willy Tarreauff011f22011-01-06 17:51:27 +01002692 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002693 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002694 else if (!strcmp(args[0], "http-response")) { /* response access control */
2695 struct http_res_rule *rule;
2696
2697 if (curproxy == &defproxy) {
2698 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2699 err_code |= ERR_ALERT | ERR_FATAL;
2700 goto out;
2701 }
2702
2703 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2704 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2705 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2706 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2707 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2708 file, linenum, args[0]);
2709 err_code |= ERR_WARN;
2710 }
2711
2712 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2713
2714 if (!rule) {
2715 err_code |= ERR_ALERT | ERR_ABORT;
2716 goto out;
2717 }
2718
2719 err_code |= warnif_cond_conflicts(rule->cond,
2720 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2721 file, linenum);
2722
2723 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2724 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002725 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2726 /* set the header name and length into the proxy structure */
2727 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2728 err_code |= ERR_WARN;
2729
2730 if (!*args[1]) {
2731 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2732 file, linenum, args[0]);
2733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
2735 }
2736
2737 /* set the desired header name */
2738 free(curproxy->server_id_hdr_name);
2739 curproxy->server_id_hdr_name = strdup(args[1]);
2740 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2741 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002742 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002743 if (curproxy == &defproxy) {
2744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002747 }
2748
Willy Tarreauef6494c2010-01-28 17:12:36 +01002749 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002750 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2751 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002754 }
2755
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002756 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2757 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2758 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002761 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002762
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002763 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002764 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002765 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002766 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002767 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002768
Cyril Bonté99ed3272010-01-24 23:29:44 +01002769 if (curproxy == &defproxy) {
2770 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002775 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002776 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2777 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002780 }
2781
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002782 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002783 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002784 err_code |= warnif_cond_conflicts(rule->cond,
2785 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2786 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002787 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002788 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002789 struct switching_rule *rule;
2790
Willy Tarreaub099aca2008-10-12 17:26:37 +02002791 if (curproxy == &defproxy) {
2792 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002795 }
2796
Willy Tarreau55ea7572007-06-17 19:56:27 +02002797 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002798 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002799
2800 if (*(args[1]) == 0) {
2801 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002804 }
2805
Willy Tarreauef6494c2010-01-28 17:12:36 +01002806 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002807 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2808 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002811 }
2812
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002813 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2814 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2815 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002818 }
2819
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002820 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002821
Willy Tarreau55ea7572007-06-17 19:56:27 +02002822 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2823 rule->cond = cond;
2824 rule->be.name = strdup(args[1]);
2825 LIST_INIT(&rule->list);
2826 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2827 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002828 else if (strcmp(args[0], "use-server") == 0) {
2829 struct server_rule *rule;
2830
2831 if (curproxy == &defproxy) {
2832 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836
2837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2838 err_code |= ERR_WARN;
2839
2840 if (*(args[1]) == 0) {
2841 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
2844 }
2845
2846 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2847 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2848 file, linenum, args[0]);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002853 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2854 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2855 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002856 err_code |= ERR_ALERT | ERR_FATAL;
2857 goto out;
2858 }
2859
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002860 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002861
2862 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2863 rule->cond = cond;
2864 rule->srv.name = strdup(args[1]);
2865 LIST_INIT(&rule->list);
2866 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2867 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2868 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002869 else if ((!strcmp(args[0], "force-persist")) ||
2870 (!strcmp(args[0], "ignore-persist"))) {
2871 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002872
2873 if (curproxy == &defproxy) {
2874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
2878
2879 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2880 err_code |= ERR_WARN;
2881
Willy Tarreauef6494c2010-01-28 17:12:36 +01002882 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002883 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2884 file, linenum, args[0]);
2885 err_code |= ERR_ALERT | ERR_FATAL;
2886 goto out;
2887 }
2888
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002889 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2890 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2891 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002892 err_code |= ERR_ALERT | ERR_FATAL;
2893 goto out;
2894 }
2895
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002896 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2897 * where force-persist is applied.
2898 */
2899 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002900
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002901 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002902 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002903 if (!strcmp(args[0], "force-persist")) {
2904 rule->type = PERSIST_TYPE_FORCE;
2905 } else {
2906 rule->type = PERSIST_TYPE_IGNORE;
2907 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002908 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002909 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002910 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002911 else if (!strcmp(args[0], "stick-table")) {
2912 int myidx = 1;
2913
Emeric Brun32da3c42010-09-23 18:39:19 +02002914 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002915 curproxy->table.type = (unsigned int)-1;
2916 while (*args[myidx]) {
2917 const char *err;
2918
2919 if (strcmp(args[myidx], "size") == 0) {
2920 myidx++;
2921 if (!*(args[myidx])) {
2922 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2923 file, linenum, args[myidx-1]);
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
2926 }
2927 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2928 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2929 file, linenum, *err, args[myidx-1]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002933 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002934 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002935 else if (strcmp(args[myidx], "peers") == 0) {
2936 myidx++;
Godbach50523162013-12-11 19:48:57 +08002937 if (!*(args[myidx])) {
2938 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2939 file, linenum, args[myidx-1]);
2940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
2942 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002943 curproxy->table.peers.name = strdup(args[myidx++]);
2944 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002945 else if (strcmp(args[myidx], "expire") == 0) {
2946 myidx++;
2947 if (!*(args[myidx])) {
2948 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2949 file, linenum, args[myidx-1]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2954 if (err) {
2955 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2956 file, linenum, *err, args[myidx-1]);
2957 err_code |= ERR_ALERT | ERR_FATAL;
2958 goto out;
2959 }
2960 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002961 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002962 }
2963 else if (strcmp(args[myidx], "nopurge") == 0) {
2964 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002965 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002966 }
2967 else if (strcmp(args[myidx], "type") == 0) {
2968 myidx++;
2969 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2970 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2971 file, linenum, args[myidx]);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002975 /* myidx already points to next arg */
2976 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002977 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002978 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002979 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002980
2981 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002982 nw = args[myidx];
2983 while (*nw) {
2984 /* the "store" keyword supports a comma-separated list */
2985 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002986 sa = NULL; /* store arg */
2987 while (*nw && *nw != ',') {
2988 if (*nw == '(') {
2989 *nw = 0;
2990 sa = ++nw;
2991 while (*nw != ')') {
2992 if (!*nw) {
2993 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2994 file, linenum, args[0], cw);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998 nw++;
2999 }
3000 *nw = '\0';
3001 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003002 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003003 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003004 if (*nw)
3005 *nw++ = '\0';
3006 type = stktable_get_data_type(cw);
3007 if (type < 0) {
3008 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3009 file, linenum, args[0], cw);
3010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
3012 }
Willy Tarreauac782882010-06-20 10:41:54 +02003013
3014 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3015 switch (err) {
3016 case PE_NONE: break;
3017 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003018 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3019 file, linenum, args[0], cw);
3020 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003021 break;
3022
3023 case PE_ARG_MISSING:
3024 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3025 file, linenum, args[0], cw);
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028
3029 case PE_ARG_NOT_USED:
3030 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3031 file, linenum, args[0], cw);
3032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
3034
3035 default:
3036 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3037 file, linenum, args[0], cw);
3038 err_code |= ERR_ALERT | ERR_FATAL;
3039 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003040 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003041 }
3042 myidx++;
3043 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003044 else {
3045 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3046 file, linenum, args[myidx]);
3047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003049 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003050 }
3051
3052 if (!curproxy->table.size) {
3053 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3054 file, linenum);
3055 err_code |= ERR_ALERT | ERR_FATAL;
3056 goto out;
3057 }
3058
3059 if (curproxy->table.type == (unsigned int)-1) {
3060 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3061 file, linenum);
3062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
3064 }
3065 }
3066 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003067 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003068 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003069 int myidx = 0;
3070 const char *name = NULL;
3071 int flags;
3072
3073 if (curproxy == &defproxy) {
3074 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3075 err_code |= ERR_ALERT | ERR_FATAL;
3076 goto out;
3077 }
3078
3079 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3080 err_code |= ERR_WARN;
3081 goto out;
3082 }
3083
3084 myidx++;
3085 if ((strcmp(args[myidx], "store") == 0) ||
3086 (strcmp(args[myidx], "store-request") == 0)) {
3087 myidx++;
3088 flags = STK_IS_STORE;
3089 }
3090 else if (strcmp(args[myidx], "store-response") == 0) {
3091 myidx++;
3092 flags = STK_IS_STORE | STK_ON_RSP;
3093 }
3094 else if (strcmp(args[myidx], "match") == 0) {
3095 myidx++;
3096 flags = STK_IS_MATCH;
3097 }
3098 else if (strcmp(args[myidx], "on") == 0) {
3099 myidx++;
3100 flags = STK_IS_MATCH | STK_IS_STORE;
3101 }
3102 else {
3103 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
3106 }
3107
3108 if (*(args[myidx]) == 0) {
3109 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003114 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003115 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003116 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003117 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121
3122 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003123 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3124 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3125 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003126 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 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003131 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3132 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3133 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003134 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003135 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003136 goto out;
3137 }
3138 }
3139
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003140 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003141 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003142
Emeric Brunb982a3d2010-01-04 15:45:53 +01003143 if (strcmp(args[myidx], "table") == 0) {
3144 myidx++;
3145 name = args[myidx++];
3146 }
3147
Willy Tarreauef6494c2010-01-28 17:12:36 +01003148 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003149 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3150 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3151 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003152 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003153 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 goto out;
3155 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003156 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003157 else if (*(args[myidx])) {
3158 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3159 file, linenum, args[0], args[myidx]);
3160 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003161 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003162 goto out;
3163 }
Emeric Brun97679e72010-09-23 17:56:44 +02003164 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003165 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003166 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003167 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003168
Emeric Brunb982a3d2010-01-04 15:45:53 +01003169 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3170 rule->cond = cond;
3171 rule->expr = expr;
3172 rule->flags = flags;
3173 rule->table.name = name ? strdup(name) : NULL;
3174 LIST_INIT(&rule->list);
3175 if (flags & STK_ON_RSP)
3176 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3177 else
3178 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003181 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003182 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003183
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3185 curproxy->uri_auth = NULL; /* we must detach from the default config */
3186
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003187 if (!*args[1]) {
3188 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003189 } else if (!strcmp(args[1], "admin")) {
3190 struct stats_admin_rule *rule;
3191
3192 if (curproxy == &defproxy) {
3193 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
3196 }
3197
3198 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3199 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3200 err_code |= ERR_ALERT | ERR_ABORT;
3201 goto out;
3202 }
3203
3204 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3205 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3206 file, linenum, args[0], args[1]);
3207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
3209 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003210 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3211 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3212 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
3215 }
3216
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003217 err_code |= warnif_cond_conflicts(cond,
3218 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3219 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003220
3221 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3222 rule->cond = cond;
3223 LIST_INIT(&rule->list);
3224 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225 } else if (!strcmp(args[1], "uri")) {
3226 if (*(args[2]) == 0) {
3227 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3231 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003232 err_code |= ERR_ALERT | ERR_ABORT;
3233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003234 }
3235 } else if (!strcmp(args[1], "realm")) {
3236 if (*(args[2]) == 0) {
3237 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3241 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_ALERT | ERR_ABORT;
3243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003245 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003246 unsigned interval;
3247
3248 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3249 if (err) {
3250 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3251 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003252 err_code |= ERR_ALERT | ERR_FATAL;
3253 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003254 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3255 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003256 err_code |= ERR_ALERT | ERR_ABORT;
3257 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003258 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003259 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003260 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003261
3262 if (curproxy == &defproxy) {
3263 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
3266 }
3267
3268 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3269 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3270 err_code |= ERR_ALERT | ERR_ABORT;
3271 goto out;
3272 }
3273
Willy Tarreauff011f22011-01-06 17:51:27 +01003274 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3275 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003276 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3277 file, linenum, args[0]);
3278 err_code |= ERR_WARN;
3279 }
3280
Willy Tarreauff011f22011-01-06 17:51:27 +01003281 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003282
Willy Tarreauff011f22011-01-06 17:51:27 +01003283 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003284 err_code |= ERR_ALERT | ERR_ABORT;
3285 goto out;
3286 }
3287
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003288 err_code |= warnif_cond_conflicts(rule->cond,
3289 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3290 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003291 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003292
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 } else if (!strcmp(args[1], "auth")) {
3294 if (*(args[2]) == 0) {
3295 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3299 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003300 err_code |= ERR_ALERT | ERR_ABORT;
3301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 }
3303 } else if (!strcmp(args[1], "scope")) {
3304 if (*(args[2]) == 0) {
3305 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3309 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_ABORT;
3311 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312 }
3313 } else if (!strcmp(args[1], "enable")) {
3314 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3315 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003316 err_code |= ERR_ALERT | ERR_ABORT;
3317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003319 } else if (!strcmp(args[1], "hide-version")) {
3320 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3321 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_ABORT;
3323 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003324 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003325 } else if (!strcmp(args[1], "show-legends")) {
3326 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3327 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3328 err_code |= ERR_ALERT | ERR_ABORT;
3329 goto out;
3330 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003331 } else if (!strcmp(args[1], "show-node")) {
3332
3333 if (*args[2]) {
3334 int i;
3335 char c;
3336
3337 for (i=0; args[2][i]; i++) {
3338 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003339 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3340 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003341 break;
3342 }
3343
3344 if (!i || args[2][i]) {
3345 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3346 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3347 file, linenum, args[0], args[1]);
3348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
3350 }
3351 }
3352
3353 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3354 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3355 err_code |= ERR_ALERT | ERR_ABORT;
3356 goto out;
3357 }
3358 } else if (!strcmp(args[1], "show-desc")) {
3359 char *desc = NULL;
3360
3361 if (*args[2]) {
3362 int i, len=0;
3363 char *d;
3364
3365 for(i=2; *args[i]; i++)
3366 len += strlen(args[i])+1;
3367
3368 desc = d = (char *)calloc(1, len);
3369
3370 d += sprintf(d, "%s", args[2]);
3371 for(i=3; *args[i]; i++)
3372 d += sprintf(d, " %s", args[i]);
3373 }
3374
3375 if (!*args[2] && !global.desc)
3376 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3377 file, linenum, args[1]);
3378 else {
3379 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3380 free(desc);
3381 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3382 err_code |= ERR_ALERT | ERR_ABORT;
3383 goto out;
3384 }
3385 free(desc);
3386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003388stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003389 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 +01003390 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 }
3394 }
3395 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003396 int optnum;
3397
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003398 if (*(args[1]) == '\0') {
3399 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3400 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003403 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003404
3405 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3406 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003407 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3408 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3409 file, linenum, cfg_opts[optnum].name);
3410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
3412 }
Willy Tarreau93893792009-07-23 13:19:11 +02003413 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3414 err_code |= ERR_WARN;
3415 goto out;
3416 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003417
Willy Tarreau3842f002009-06-14 11:39:52 +02003418 curproxy->no_options &= ~cfg_opts[optnum].val;
3419 curproxy->options &= ~cfg_opts[optnum].val;
3420
3421 switch (kwm) {
3422 case KWM_STD:
3423 curproxy->options |= cfg_opts[optnum].val;
3424 break;
3425 case KWM_NO:
3426 curproxy->no_options |= cfg_opts[optnum].val;
3427 break;
3428 case KWM_DEF: /* already cleared */
3429 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003430 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003431
Willy Tarreau93893792009-07-23 13:19:11 +02003432 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003433 }
3434 }
3435
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003436 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3437 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003438 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3439 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3440 file, linenum, cfg_opts2[optnum].name);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
Willy Tarreau93893792009-07-23 13:19:11 +02003444 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3445 err_code |= ERR_WARN;
3446 goto out;
3447 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003448
Willy Tarreau3842f002009-06-14 11:39:52 +02003449 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3450 curproxy->options2 &= ~cfg_opts2[optnum].val;
3451
3452 switch (kwm) {
3453 case KWM_STD:
3454 curproxy->options2 |= cfg_opts2[optnum].val;
3455 break;
3456 case KWM_NO:
3457 curproxy->no_options2 |= cfg_opts2[optnum].val;
3458 break;
3459 case KWM_DEF: /* already cleared */
3460 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003461 }
Willy Tarreau93893792009-07-23 13:19:11 +02003462 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003463 }
3464 }
3465
Willy Tarreau3842f002009-06-14 11:39:52 +02003466 if (kwm != KWM_STD) {
3467 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003468 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003471 }
3472
Emeric Brun3a058f32009-06-30 18:26:00 +02003473 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003474 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003476 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003477 if (*(args[2]) != '\0') {
3478 if (!strcmp(args[2], "clf")) {
3479 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003480 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003481 } else {
3482 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003485 }
3486 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003487 if (curproxy->conf.logformat_string != default_http_log_format &&
3488 curproxy->conf.logformat_string != default_tcp_log_format &&
3489 curproxy->conf.logformat_string != clf_http_log_format)
3490 free(curproxy->conf.logformat_string);
3491 curproxy->conf.logformat_string = logformat;
3492
3493 free(curproxy->conf.lfs_file);
3494 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3495 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003496 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003497 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003499 if (curproxy->conf.logformat_string != default_http_log_format &&
3500 curproxy->conf.logformat_string != default_tcp_log_format &&
3501 curproxy->conf.logformat_string != clf_http_log_format)
3502 free(curproxy->conf.logformat_string);
3503 curproxy->conf.logformat_string = default_tcp_log_format;
3504
3505 free(curproxy->conf.lfs_file);
3506 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3507 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 else if (!strcmp(args[1], "tcpka")) {
3510 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003511 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003512 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003513
3514 if (curproxy->cap & PR_CAP_FE)
3515 curproxy->options |= PR_O_TCP_CLI_KA;
3516 if (curproxy->cap & PR_CAP_BE)
3517 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 }
3519 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003520 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003521 err_code |= ERR_WARN;
3522
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003524 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003525 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003526 curproxy->options2 &= ~PR_O2_CHK_ANY;
3527 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003528 if (!*args[2]) { /* no argument */
3529 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3530 curproxy->check_len = strlen(DEF_CHECK_REQ);
3531 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003532 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 curproxy->check_req = (char *)malloc(reqlen);
3534 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003535 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003537 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 if (*args[4])
3539 reqlen += strlen(args[4]);
3540 else
3541 reqlen += strlen("HTTP/1.0");
3542
3543 curproxy->check_req = (char *)malloc(reqlen);
3544 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003545 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003547 }
3548 else if (!strcmp(args[1], "ssl-hello-chk")) {
3549 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003550 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003552
Willy Tarreaua534fea2008-08-03 12:19:50 +02003553 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003554 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003555 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003556 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 }
Willy Tarreau23677902007-05-08 23:50:35 +02003558 else if (!strcmp(args[1], "smtpchk")) {
3559 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003560 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003561 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003562 curproxy->options2 &= ~PR_O2_CHK_ANY;
3563 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003564
3565 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3566 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3567 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3568 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3569 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3570 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3571 curproxy->check_req = (char *)malloc(reqlen);
3572 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3573 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3574 } else {
3575 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3576 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3577 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3578 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3579 }
3580 }
3581 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003582 else if (!strcmp(args[1], "pgsql-check")) {
3583 /* use PostgreSQL request to check servers' health */
3584 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3585 err_code |= ERR_WARN;
3586
3587 free(curproxy->check_req);
3588 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003589 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003590 curproxy->options2 |= PR_O2_PGSQL_CHK;
3591
3592 if (*(args[2])) {
3593 int cur_arg = 2;
3594
3595 while (*(args[cur_arg])) {
3596 if (strcmp(args[cur_arg], "user") == 0) {
3597 char * packet;
3598 uint32_t packet_len;
3599 uint32_t pv;
3600
3601 /* suboption header - needs additional argument for it */
3602 if (*(args[cur_arg+1]) == 0) {
3603 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3604 file, linenum, args[0], args[1], args[cur_arg]);
3605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
3607 }
3608
3609 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3610 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3611 pv = htonl(0x30000); /* protocol version 3.0 */
3612
3613 packet = (char*) calloc(1, packet_len);
3614
3615 memcpy(packet + 4, &pv, 4);
3616
3617 /* copy "user" */
3618 memcpy(packet + 8, "user", 4);
3619
3620 /* copy username */
3621 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3622
3623 free(curproxy->check_req);
3624 curproxy->check_req = packet;
3625 curproxy->check_len = packet_len;
3626
3627 packet_len = htonl(packet_len);
3628 memcpy(packet, &packet_len, 4);
3629 cur_arg += 2;
3630 } else {
3631 /* unknown suboption - catchall */
3632 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3633 file, linenum, args[0], args[1]);
3634 err_code |= ERR_ALERT | ERR_FATAL;
3635 goto out;
3636 }
3637 } /* end while loop */
3638 }
3639 }
3640
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003641 else if (!strcmp(args[1], "redis-check")) {
3642 /* use REDIS PING request to check servers' health */
3643 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3644 err_code |= ERR_WARN;
3645
3646 free(curproxy->check_req);
3647 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003648 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003649 curproxy->options2 |= PR_O2_REDIS_CHK;
3650
3651 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3652 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3653 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3654 }
3655
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003656 else if (!strcmp(args[1], "mysql-check")) {
3657 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3659 err_code |= ERR_WARN;
3660
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003661 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003662 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003663 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003664 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003665
3666 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3667 * const char mysql40_client_auth_pkt[] = {
3668 * "\x0e\x00\x00" // packet length
3669 * "\x01" // packet number
3670 * "\x00\x00" // client capabilities
3671 * "\x00\x00\x01" // max packet
3672 * "haproxy\x00" // username (null terminated string)
3673 * "\x00" // filler (always 0x00)
3674 * "\x01\x00\x00" // packet length
3675 * "\x00" // packet number
3676 * "\x01" // COM_QUIT command
3677 * };
3678 */
3679
3680 if (*(args[2])) {
3681 int cur_arg = 2;
3682
3683 while (*(args[cur_arg])) {
3684 if (strcmp(args[cur_arg], "user") == 0) {
3685 char *mysqluser;
3686 int packetlen, reqlen, userlen;
3687
3688 /* suboption header - needs additional argument for it */
3689 if (*(args[cur_arg+1]) == 0) {
3690 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3691 file, linenum, args[0], args[1], args[cur_arg]);
3692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
3694 }
3695 mysqluser = args[cur_arg + 1];
3696 userlen = strlen(mysqluser);
3697 packetlen = userlen + 7;
3698 reqlen = packetlen + 9;
3699
3700 free(curproxy->check_req);
3701 curproxy->check_req = (char *)calloc(1, reqlen);
3702 curproxy->check_len = reqlen;
3703
3704 snprintf(curproxy->check_req, 4, "%c%c%c",
3705 ((unsigned char) packetlen & 0xff),
3706 ((unsigned char) (packetlen >> 8) & 0xff),
3707 ((unsigned char) (packetlen >> 16) & 0xff));
3708
3709 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003710 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003711 curproxy->check_req[8] = 1;
3712 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3713 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3714 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3715 cur_arg += 2;
3716 } else {
3717 /* unknown suboption - catchall */
3718 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3719 file, linenum, args[0], args[1]);
3720 err_code |= ERR_ALERT | ERR_FATAL;
3721 goto out;
3722 }
3723 } /* end while loop */
3724 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003725 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003726 else if (!strcmp(args[1], "ldap-check")) {
3727 /* use LDAP request to check servers' health */
3728 free(curproxy->check_req);
3729 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003730 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003731 curproxy->options2 |= PR_O2_LDAP_CHK;
3732
3733 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3734 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3735 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3736 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003737 else if (!strcmp(args[1], "tcp-check")) {
3738 /* use raw TCPCHK send/expect to check servers' health */
3739 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3740 err_code |= ERR_WARN;
3741
3742 free(curproxy->check_req);
3743 curproxy->check_req = NULL;
3744 curproxy->options2 &= ~PR_O2_CHK_ANY;
3745 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3746 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003747 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003748 int cur_arg;
3749
3750 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3751 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003752 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003753
Willy Tarreau87cf5142011-08-19 22:57:24 +02003754 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003755
3756 free(curproxy->fwdfor_hdr_name);
3757 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3758 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3759
3760 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3761 cur_arg = 2;
3762 while (*(args[cur_arg])) {
3763 if (!strcmp(args[cur_arg], "except")) {
3764 /* suboption except - needs additional argument for it */
3765 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3766 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3767 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003768 err_code |= ERR_ALERT | ERR_FATAL;
3769 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003770 }
3771 /* flush useless bits */
3772 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003773 cur_arg += 2;
3774 } else if (!strcmp(args[cur_arg], "header")) {
3775 /* suboption header - needs additional argument for it */
3776 if (*(args[cur_arg+1]) == 0) {
3777 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3778 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003781 }
3782 free(curproxy->fwdfor_hdr_name);
3783 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3784 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3785 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003786 } else if (!strcmp(args[cur_arg], "if-none")) {
3787 curproxy->options &= ~PR_O_FF_ALWAYS;
3788 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003789 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003790 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003791 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003792 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003795 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003796 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003797 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003798 else if (!strcmp(args[1], "originalto")) {
3799 int cur_arg;
3800
3801 /* insert x-original-to field, but not for the IP address listed as an except.
3802 * set default options (ie: bitfield, header name, etc)
3803 */
3804
3805 curproxy->options |= PR_O_ORGTO;
3806
3807 free(curproxy->orgto_hdr_name);
3808 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3809 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3810
Willy Tarreau87cf5142011-08-19 22:57:24 +02003811 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003812 cur_arg = 2;
3813 while (*(args[cur_arg])) {
3814 if (!strcmp(args[cur_arg], "except")) {
3815 /* suboption except - needs additional argument for it */
3816 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3817 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3818 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003821 }
3822 /* flush useless bits */
3823 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3824 cur_arg += 2;
3825 } else if (!strcmp(args[cur_arg], "header")) {
3826 /* suboption header - needs additional argument for it */
3827 if (*(args[cur_arg+1]) == 0) {
3828 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3829 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003832 }
3833 free(curproxy->orgto_hdr_name);
3834 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3835 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3836 cur_arg += 2;
3837 } else {
3838 /* unknown suboption - catchall */
3839 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3840 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003843 }
3844 } /* end while loop */
3845 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 else {
3847 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_FATAL;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
Willy Tarreau93893792009-07-23 13:19:11 +02003851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003853 else if (!strcmp(args[0], "default_backend")) {
3854 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003856
3857 if (*(args[1]) == 0) {
3858 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003861 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003862 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003863 curproxy->defbe.name = strdup(args[1]);
3864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003865 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003866 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003868
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003869 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3870 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003871 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 /* enable reconnections to dispatch */
3873 curproxy->options |= PR_O_REDISP;
3874 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003875 else if (!strcmp(args[0], "http-check")) {
3876 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003878
3879 if (strcmp(args[1], "disable-on-404") == 0) {
3880 /* enable a graceful server shutdown on an HTTP 404 response */
3881 curproxy->options |= PR_O_DISABLE404;
3882 }
Willy Tarreauef781042010-01-27 11:53:01 +01003883 else if (strcmp(args[1], "send-state") == 0) {
3884 /* enable emission of the apparent state of a server in HTTP checks */
3885 curproxy->options2 |= PR_O2_CHK_SNDST;
3886 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003887 else if (strcmp(args[1], "expect") == 0) {
3888 const char *ptr_arg;
3889 int cur_arg;
3890
3891 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3892 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3893 err_code |= ERR_ALERT | ERR_FATAL;
3894 goto out;
3895 }
3896
3897 cur_arg = 2;
3898 /* consider exclamation marks, sole or at the beginning of a word */
3899 while (*(ptr_arg = args[cur_arg])) {
3900 while (*ptr_arg == '!') {
3901 curproxy->options2 ^= PR_O2_EXP_INV;
3902 ptr_arg++;
3903 }
3904 if (*ptr_arg)
3905 break;
3906 cur_arg++;
3907 }
3908 /* now ptr_arg points to the beginning of a word past any possible
3909 * exclamation mark, and cur_arg is the argument which holds this word.
3910 */
3911 if (strcmp(ptr_arg, "status") == 0) {
3912 if (!*(args[cur_arg + 1])) {
3913 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3914 file, linenum, args[0], args[1], ptr_arg);
3915 err_code |= ERR_ALERT | ERR_FATAL;
3916 goto out;
3917 }
3918 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003919 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003920 curproxy->expect_str = strdup(args[cur_arg + 1]);
3921 }
3922 else if (strcmp(ptr_arg, "string") == 0) {
3923 if (!*(args[cur_arg + 1])) {
3924 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3925 file, linenum, args[0], args[1], ptr_arg);
3926 err_code |= ERR_ALERT | ERR_FATAL;
3927 goto out;
3928 }
3929 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003930 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003931 curproxy->expect_str = strdup(args[cur_arg + 1]);
3932 }
3933 else if (strcmp(ptr_arg, "rstatus") == 0) {
3934 if (!*(args[cur_arg + 1])) {
3935 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3936 file, linenum, args[0], args[1], ptr_arg);
3937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
3939 }
3940 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003941 free(curproxy->expect_str);
3942 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3943 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003944 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3945 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3946 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3947 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
3951 }
3952 else if (strcmp(ptr_arg, "rstring") == 0) {
3953 if (!*(args[cur_arg + 1])) {
3954 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3955 file, linenum, args[0], args[1], ptr_arg);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
3959 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003960 free(curproxy->expect_str);
3961 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3962 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003963 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3964 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3965 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3966 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3967 err_code |= ERR_ALERT | ERR_FATAL;
3968 goto out;
3969 }
3970 }
3971 else {
3972 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3973 file, linenum, args[0], args[1], ptr_arg);
3974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
3976 }
3977 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003978 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003979 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 +02003980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003982 }
3983 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003984 else if (!strcmp(args[0], "tcp-check")) {
3985 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3986 err_code |= ERR_WARN;
3987
3988 if (strcmp(args[1], "send") == 0) {
3989 if (! *(args[2]) ) {
3990 /* SEND string expected */
3991 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
3992 file, linenum, args[0], args[1], args[2]);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 } else {
3996 struct tcpcheck_rule *tcpcheck;
3997
3998 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
3999
4000 tcpcheck->action = TCPCHK_ACT_SEND;
4001 tcpcheck->string_len = strlen(args[2]);
4002 tcpcheck->string = strdup(args[2]);
4003 tcpcheck->expect_regex = NULL;
4004
4005 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4006 }
4007 }
4008 else if (strcmp(args[1], "send-binary") == 0) {
4009 if (! *(args[2]) ) {
4010 /* SEND binary string expected */
4011 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4012 file, linenum, args[0], args[1], args[2]);
4013 err_code |= ERR_ALERT | ERR_FATAL;
4014 goto out;
4015 } else {
4016 struct tcpcheck_rule *tcpcheck;
4017 char *err = NULL;
4018
4019 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4020
4021 tcpcheck->action = TCPCHK_ACT_SEND;
4022 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4023 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4024 file, linenum, args[0], args[1], args[2], err);
4025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
4027 }
4028 tcpcheck->expect_regex = NULL;
4029
4030 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4031 }
4032 }
4033 else if (strcmp(args[1], "expect") == 0) {
4034 const char *ptr_arg;
4035 int cur_arg;
4036 int inverse = 0;
4037
4038 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4039 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4040 err_code |= ERR_ALERT | ERR_FATAL;
4041 goto out;
4042 }
4043
4044 cur_arg = 2;
4045 /* consider exclamation marks, sole or at the beginning of a word */
4046 while (*(ptr_arg = args[cur_arg])) {
4047 while (*ptr_arg == '!') {
4048 inverse = !inverse;
4049 ptr_arg++;
4050 }
4051 if (*ptr_arg)
4052 break;
4053 cur_arg++;
4054 }
4055 /* now ptr_arg points to the beginning of a word past any possible
4056 * exclamation mark, and cur_arg is the argument which holds this word.
4057 */
4058 if (strcmp(ptr_arg, "binary") == 0) {
4059 if (!*(args[cur_arg + 1])) {
4060 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4061 file, linenum, args[0], args[1], ptr_arg);
4062 err_code |= ERR_ALERT | ERR_FATAL;
4063 goto out;
4064 }
4065 struct tcpcheck_rule *tcpcheck;
4066 char *err = NULL;
4067
4068 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4069
4070 tcpcheck->action = TCPCHK_ACT_EXPECT;
4071 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4072 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4073 file, linenum, args[0], args[1], args[2], err);
4074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077 tcpcheck->expect_regex = NULL;
4078 tcpcheck->inverse = inverse;
4079
4080 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4081 }
4082 else if (strcmp(ptr_arg, "string") == 0) {
4083 if (!*(args[cur_arg + 1])) {
4084 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4085 file, linenum, args[0], args[1], ptr_arg);
4086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
4088 }
4089 struct tcpcheck_rule *tcpcheck;
4090
4091 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4092
4093 tcpcheck->action = TCPCHK_ACT_EXPECT;
4094 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4095 tcpcheck->string = strdup(args[cur_arg + 1]);
4096 tcpcheck->expect_regex = NULL;
4097 tcpcheck->inverse = inverse;
4098
4099 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4100 }
4101 else if (strcmp(ptr_arg, "rstring") == 0) {
4102 if (!*(args[cur_arg + 1])) {
4103 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4104 file, linenum, args[0], args[1], ptr_arg);
4105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
4107 }
4108 struct tcpcheck_rule *tcpcheck;
4109
4110 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4111
4112 tcpcheck->action = TCPCHK_ACT_EXPECT;
4113 tcpcheck->string_len = 0;
4114 tcpcheck->string = NULL;
4115 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4116 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4117 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4118 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4119 err_code |= ERR_ALERT | ERR_FATAL;
4120 goto out;
4121 }
4122 tcpcheck->inverse = inverse;
4123
4124 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4125 }
4126 else {
4127 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4128 file, linenum, args[0], args[1], ptr_arg);
4129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
4131 }
4132 }
4133 else {
4134 Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
4135 err_code |= ERR_ALERT | ERR_FATAL;
4136 goto out;
4137 }
4138 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004139 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004140 if (curproxy == &defproxy) {
4141 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004142 err_code |= ERR_ALERT | ERR_FATAL;
4143 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004144 }
4145
Willy Tarreaub80c2302007-11-30 20:51:32 +01004146 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004147 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004148
4149 if (strcmp(args[1], "fail") == 0) {
4150 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004151 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004152 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4153 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004156 }
4157
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004158 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4159 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4160 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004163 }
4164 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4165 }
4166 else {
4167 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004170 }
4171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004172#ifdef TPROXY
4173 else if (!strcmp(args[0], "transparent")) {
4174 /* enable transparent proxy connections */
4175 curproxy->options |= PR_O_TRANSP;
4176 }
4177#endif
4178 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004179 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004181
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 if (*(args[1]) == 0) {
4183 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004186 }
4187 curproxy->maxconn = atol(args[1]);
4188 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004189 else if (!strcmp(args[0], "backlog")) { /* backlog */
4190 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004192
4193 if (*(args[1]) == 0) {
4194 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004197 }
4198 curproxy->backlog = atol(args[1]);
4199 }
Willy Tarreau86034312006-12-29 00:10:33 +01004200 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004201 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004202 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004203
Willy Tarreau86034312006-12-29 00:10:33 +01004204 if (*(args[1]) == 0) {
4205 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004208 }
4209 curproxy->fullconn = atol(args[1]);
4210 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004211 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4212 if (*(args[1]) == 0) {
4213 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004216 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004217 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4218 if (err) {
4219 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4220 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004223 }
4224 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 }
4226 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004227 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004228 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004229 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004230
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 if (curproxy == &defproxy) {
4232 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004236 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004237 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004238
Willy Tarreau902636f2013-03-10 19:44:48 +01004239 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004240 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004241 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004242 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004243 goto out;
4244 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004245
4246 proto = protocol_by_family(sk->ss_family);
4247 if (!proto || !proto->connect) {
4248 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4249 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
4252 }
4253
4254 if (port1 != port2) {
4255 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4256 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004257 err_code |= ERR_ALERT | ERR_FATAL;
4258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004259 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004260
4261 if (!port1) {
4262 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4263 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004264 err_code |= ERR_ALERT | ERR_FATAL;
4265 goto out;
4266 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004267
Willy Tarreaud5191e72010-02-09 20:50:45 +01004268 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004269 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004270 }
4271 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004272 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004273 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004274
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004275 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4276 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004281 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004282 /**
4283 * The syntax for hash-type config element is
4284 * hash-type {map-based|consistent} [[<algo>] avalanche]
4285 *
4286 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4287 */
4288 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004289
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004290 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4291 err_code |= ERR_WARN;
4292
4293 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004294 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4295 }
4296 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004297 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4298 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004299 else if (strcmp(args[1], "avalanche") == 0) {
4300 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004303 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004304 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004305 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
Bhaskar98634f02013-10-29 23:30:51 -04004309
4310 /* set the hash function to use */
4311 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004312 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004313 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004314
4315 /* if consistent with no argument, then avalanche modifier is also applied */
4316 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4317 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004318 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004319 /* set the hash function */
4320 if (!strcmp(args[2], "sdbm")) {
4321 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4322 }
4323 else if (!strcmp(args[2], "djb2")) {
4324 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004325 } else if (!strcmp(args[2], "wt6")) {
4326 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004327 }
4328 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004329 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004330 err_code |= ERR_ALERT | ERR_FATAL;
4331 goto out;
4332 }
4333
4334 /* set the hash modifier */
4335 if (!strcmp(args[3], "avalanche")) {
4336 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4337 }
4338 else if (*args[3]) {
4339 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342 }
Bhaskar98634f02013-10-29 23:30:51 -04004343 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004344 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004345 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004347 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004348 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004350 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004351 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
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 Tarreau977b8e42006-12-29 14:19:17 +01004355 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004356 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004357
4358 if (!*args[2]) {
4359 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4360 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004364
4365 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004366 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004367 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4368 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004371 }
4372
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004373 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004374 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004375 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004376 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004377
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004378 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4379 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4380 err_code |= ERR_ALERT | ERR_ABORT;
4381 goto out;
4382 }
4383
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004384 /* the servers are linked backwards first */
4385 newsrv->next = curproxy->srv;
4386 curproxy->srv = newsrv;
4387 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004388 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004389 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004391 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004392 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004393 LIST_INIT(&newsrv->pendconns);
4394 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004395 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004396 newsrv->state = SRV_RUNNING; /* early server setup */
4397 newsrv->last_change = now.tv_sec;
4398 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004400 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004401 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004402 * - IP: => port=+0, relative
4403 * - IP:N => port=N, absolute
4404 * - IP:+N => port=+N, relative
4405 * - IP:-N => port=-N, relative
4406 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004407 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004408 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004409 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004410 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004411 goto out;
4412 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004413
4414 proto = protocol_by_family(sk->ss_family);
4415 if (!proto || !proto->connect) {
4416 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4417 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
4420 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004421
4422 if (!port1 || !port2) {
4423 /* no port specified, +offset, -offset */
4424 newsrv->state |= SRV_MAPPORTS;
4425 }
4426 else if (port1 != port2) {
4427 /* port range */
4428 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4429 file, linenum, args[0], args[1], args[2]);
4430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
4432 }
4433 else {
4434 /* used by checks */
4435 realport = port1;
4436 }
4437
Willy Tarreaud5191e72010-02-09 20:50:45 +01004438 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004439 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4440 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004441
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004442 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004443 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4444 file, linenum, newsrv->addr.ss_family, args[2]);
4445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
4447 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004448
Simon Hormand60d6912013-11-25 10:46:36 +09004449 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004450 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004451 newsrv->check.inter = curproxy->defsrv.check.inter;
4452 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4453 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004454 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4455 newsrv->agent.port = curproxy->defsrv.agent.port;
4456 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4457 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4458 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004459 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4460 newsrv->minconn = curproxy->defsrv.minconn;
4461 newsrv->maxconn = curproxy->defsrv.maxconn;
4462 newsrv->slowstart = curproxy->defsrv.slowstart;
4463 newsrv->onerror = curproxy->defsrv.onerror;
4464 newsrv->consecutive_errors_limit
4465 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004466#ifdef OPENSSL
4467 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4468#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004469 newsrv->uweight = newsrv->iweight
4470 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004471
Simon Horman69d29f92013-02-23 15:14:19 +09004472 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004473 newsrv->check.rise = curproxy->defsrv.check.rise;
4474 newsrv->check.fall = curproxy->defsrv.check.fall;
4475 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004476 newsrv->check.server = newsrv;
4477
Simon Hormand60d6912013-11-25 10:46:36 +09004478 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004479 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4480 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4481 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004482 newsrv->agent.server = newsrv;
4483
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004484 cur_arg = 3;
4485 } else {
4486 newsrv = &curproxy->defsrv;
4487 cur_arg = 1;
4488 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004489
Willy Tarreaubaaee002006-06-26 02:48:02 +02004490 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004491 if (!strcmp(args[cur_arg], "agent-check")) {
4492 global.maxsock++;
4493 do_agent = 1;
4494 cur_arg += 1;
4495 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4496 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4497 if (err) {
4498 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4499 file, linenum, *err, newsrv->id);
4500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
4502 }
4503 if (val <= 0) {
4504 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4505 file, linenum, val, args[cur_arg], newsrv->id);
4506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
4508 }
4509 newsrv->agent.inter = val;
4510 cur_arg += 2;
4511 }
4512 else if (!strcmp(args[cur_arg], "agent-port")) {
4513 global.maxsock++;
4514 newsrv->agent.port = atol(args[cur_arg + 1]);
4515 cur_arg += 2;
4516 }
4517 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 newsrv->cookie = strdup(args[cur_arg + 1]);
4519 newsrv->cklen = strlen(args[cur_arg + 1]);
4520 cur_arg += 2;
4521 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004522 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004523 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4524 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4525 cur_arg += 2;
4526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004527 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004528 if (!*args[cur_arg + 1]) {
4529 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4530 file, linenum, args[cur_arg]);
4531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
4533 }
4534
Simon Horman58c32972013-11-25 10:46:38 +09004535 newsrv->check.rise = atol(args[cur_arg + 1]);
4536 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004537 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4538 file, linenum, args[cur_arg]);
4539 err_code |= ERR_ALERT | ERR_FATAL;
4540 goto out;
4541 }
4542
Simon Horman125d0992013-02-24 17:23:38 +09004543 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004544 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 cur_arg += 2;
4546 }
4547 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004548 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004549
4550 if (!*args[cur_arg + 1]) {
4551 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4552 file, linenum, args[cur_arg]);
4553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
4555 }
4556
Simon Horman58c32972013-11-25 10:46:38 +09004557 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004558 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4559 file, linenum, args[cur_arg]);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
4563
Willy Tarreaubaaee002006-06-26 02:48:02 +02004564 cur_arg += 2;
4565 }
4566 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004567 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4568 if (err) {
4569 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4570 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004571 err_code |= ERR_ALERT | ERR_FATAL;
4572 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004573 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004574 if (val <= 0) {
4575 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4576 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004579 }
Simon Horman66183002013-02-23 10:16:43 +09004580 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004581 cur_arg += 2;
4582 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004583 else if (!strcmp(args[cur_arg], "fastinter")) {
4584 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4585 if (err) {
4586 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4587 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004590 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004591 if (val <= 0) {
4592 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4593 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_ALERT | ERR_FATAL;
4595 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004596 }
Simon Horman66183002013-02-23 10:16:43 +09004597 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004598 cur_arg += 2;
4599 }
4600 else if (!strcmp(args[cur_arg], "downinter")) {
4601 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4602 if (err) {
4603 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4604 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004605 err_code |= ERR_ALERT | ERR_FATAL;
4606 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004607 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004608 if (val <= 0) {
4609 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4610 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004613 }
Simon Horman66183002013-02-23 10:16:43 +09004614 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004615 cur_arg += 2;
4616 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004617 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004618 struct sockaddr_storage *sk;
4619 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004620 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004621
Willy Tarreau902636f2013-03-10 19:44:48 +01004622 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004623 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004624 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004625 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004626 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004627 goto out;
4628 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004629
4630 proto = protocol_by_family(sk->ss_family);
4631 if (!proto || !proto->connect) {
4632 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004633 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004634 err_code |= ERR_ALERT | ERR_FATAL;
4635 goto out;
4636 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004637
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004638 if (port1 != port2) {
4639 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4640 file, linenum, args[cur_arg], args[cur_arg + 1]);
4641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
4644
Simon Horman66183002013-02-23 10:16:43 +09004645 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004646 cur_arg += 2;
4647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004649 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004650 cur_arg += 2;
4651 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004652 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004653 newsrv->state |= SRV_BACKUP;
4654 cur_arg ++;
4655 }
Simon Hormanfa461682011-06-25 09:39:49 +09004656 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4657 newsrv->state |= SRV_NON_STICK;
4658 cur_arg ++;
4659 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004660 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4661 newsrv->state |= SRV_SEND_PROXY;
4662 cur_arg ++;
4663 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004664 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4665 newsrv->check.send_proxy = 1;
4666 cur_arg ++;
4667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 else if (!strcmp(args[cur_arg], "weight")) {
4669 int w;
4670 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004671 if (w < 0 || w > SRV_UWGHT_MAX) {
4672 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4673 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004677 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 cur_arg += 2;
4679 }
4680 else if (!strcmp(args[cur_arg], "minconn")) {
4681 newsrv->minconn = atol(args[cur_arg + 1]);
4682 cur_arg += 2;
4683 }
4684 else if (!strcmp(args[cur_arg], "maxconn")) {
4685 newsrv->maxconn = atol(args[cur_arg + 1]);
4686 cur_arg += 2;
4687 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004688 else if (!strcmp(args[cur_arg], "maxqueue")) {
4689 newsrv->maxqueue = atol(args[cur_arg + 1]);
4690 cur_arg += 2;
4691 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004692 else if (!strcmp(args[cur_arg], "slowstart")) {
4693 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004694 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004695 if (err) {
4696 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4697 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004700 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004701 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004702 cur_arg += 2;
4703 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004704 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004705
4706 if (!*args[cur_arg + 1]) {
4707 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4708 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004711 }
4712
4713 newsrv->trackit = strdup(args[cur_arg + 1]);
4714
4715 cur_arg += 2;
4716 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004717 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 global.maxsock++;
4719 do_check = 1;
4720 cur_arg += 1;
4721 }
Willy Tarreau96839092010-03-29 10:02:24 +02004722 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4723 newsrv->state |= SRV_MAINTAIN;
4724 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004725 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004726 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004727 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004728 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004729 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004730 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004731 if (!strcmp(args[cur_arg + 1], "none"))
4732 newsrv->observe = HANA_OBS_NONE;
4733 else if (!strcmp(args[cur_arg + 1], "layer4"))
4734 newsrv->observe = HANA_OBS_LAYER4;
4735 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4736 if (curproxy->mode != PR_MODE_HTTP) {
4737 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4738 file, linenum, args[cur_arg + 1]);
4739 err_code |= ERR_ALERT;
4740 }
4741 newsrv->observe = HANA_OBS_LAYER7;
4742 }
4743 else {
4744 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004745 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004746 file, linenum, args[cur_arg], args[cur_arg + 1]);
4747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
4749 }
4750
4751 cur_arg += 2;
4752 }
4753 else if (!strcmp(args[cur_arg], "on-error")) {
4754 if (!strcmp(args[cur_arg + 1], "fastinter"))
4755 newsrv->onerror = HANA_ONERR_FASTINTER;
4756 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4757 newsrv->onerror = HANA_ONERR_FAILCHK;
4758 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4759 newsrv->onerror = HANA_ONERR_SUDDTH;
4760 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4761 newsrv->onerror = HANA_ONERR_MARKDWN;
4762 else {
4763 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004764 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004765 file, linenum, args[cur_arg], args[cur_arg + 1]);
4766 err_code |= ERR_ALERT | ERR_FATAL;
4767 goto out;
4768 }
4769
4770 cur_arg += 2;
4771 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004772 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4773 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4774 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4775 else {
4776 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4777 file, linenum, args[cur_arg], args[cur_arg + 1]);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
4781
4782 cur_arg += 2;
4783 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004784 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4785 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4786 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4787 else {
4788 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4789 file, linenum, args[cur_arg], args[cur_arg + 1]);
4790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
4792 }
4793
4794 cur_arg += 2;
4795 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004796 else if (!strcmp(args[cur_arg], "error-limit")) {
4797 if (!*args[cur_arg + 1]) {
4798 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4799 file, linenum, args[cur_arg]);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
4803
4804 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4805
4806 if (newsrv->consecutive_errors_limit <= 0) {
4807 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4808 file, linenum, args[cur_arg]);
4809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
4811 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004812 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004813 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004814 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004815 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004816 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004817 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004818
Willy Tarreaubaaee002006-06-26 02:48:02 +02004819 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004820 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4821 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004822 err_code |= ERR_ALERT | ERR_FATAL;
4823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004824 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004825
Willy Tarreauef9a3602012-12-08 22:29:20 +01004826 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004827 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004828 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004829 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004830 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004831 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004832 goto out;
4833 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004834
4835 proto = protocol_by_family(sk->ss_family);
4836 if (!proto || !proto->connect) {
4837 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4838 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
4841 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004842
Willy Tarreauef9a3602012-12-08 22:29:20 +01004843 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004844
4845 if (port_low != port_high) {
4846 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004847
4848 if (!port_low || !port_high) {
4849 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4850 file, linenum, args[cur_arg], args[cur_arg + 1]);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004855 if (port_low <= 0 || port_low > 65535 ||
4856 port_high <= 0 || port_high > 65535 ||
4857 port_low > port_high) {
4858 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4859 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004862 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004863 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4864 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4865 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004866 }
4867
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004869 while (*(args[cur_arg])) {
4870 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004871#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4872#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004873 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004874 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4875 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004878 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004879#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004880 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004881 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004882 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004883 err_code |= ERR_ALERT | ERR_FATAL;
4884 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004885 }
4886 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004887 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4888 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004889 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004890 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4891 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004892 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4893 char *name, *end;
4894
4895 name = args[cur_arg+1] + 7;
4896 while (isspace(*name))
4897 name++;
4898
4899 end = name;
4900 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4901 end++;
4902
Willy Tarreauef9a3602012-12-08 22:29:20 +01004903 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4904 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4905 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4906 newsrv->conn_src.bind_hdr_len = end - name;
4907 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4908 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4909 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004910
4911 /* now look for an occurrence number */
4912 while (isspace(*end))
4913 end++;
4914 if (*end == ',') {
4915 end++;
4916 name = end;
4917 if (*end == '-')
4918 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004919 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004920 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004921 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004922 }
4923
Willy Tarreauef9a3602012-12-08 22:29:20 +01004924 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004925 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4926 " occurrences values smaller than %d.\n",
4927 file, linenum, MAX_HDR_HISTORY);
4928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
4930 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004931 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004932 struct sockaddr_storage *sk;
4933 int port1, port2;
4934
Willy Tarreau902636f2013-03-10 19:44:48 +01004935 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004936 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004937 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004938 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004939 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004940 goto out;
4941 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004942
4943 proto = protocol_by_family(sk->ss_family);
4944 if (!proto || !proto->connect) {
4945 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4946 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004947 err_code |= ERR_ALERT | ERR_FATAL;
4948 goto out;
4949 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004950
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004951 if (port1 != port2) {
4952 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4953 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
4956 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004957 newsrv->conn_src.tproxy_addr = *sk;
4958 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004959 }
4960 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004961#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004962 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004963#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004964 cur_arg += 2;
4965 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004966#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004967 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004968 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004971#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004972 } /* "usesrc" */
4973
4974 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4975#ifdef SO_BINDTODEVICE
4976 if (!*args[cur_arg + 1]) {
4977 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4978 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004979 err_code |= ERR_ALERT | ERR_FATAL;
4980 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004981 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004982 free(newsrv->conn_src.iface_name);
4983 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
4984 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01004985 global.last_checks |= LSTCHK_NETADM;
4986#else
4987 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4988 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004991#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004992 cur_arg += 2;
4993 continue;
4994 }
4995 /* this keyword in not an option of "source" */
4996 break;
4997 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004999 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005000 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5001 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005006 static int srv_dumped;
5007 struct srv_kw *kw;
5008 char *err;
5009
5010 kw = srv_find_kw(args[cur_arg]);
5011 if (kw) {
5012 char *err = NULL;
5013 int code;
5014
5015 if (!kw->parse) {
5016 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5017 file, linenum, args[0], args[1], args[cur_arg]);
5018 cur_arg += 1 + kw->skip ;
5019 err_code |= ERR_ALERT | ERR_FATAL;
5020 goto out;
5021 }
5022
5023 if (defsrv && !kw->default_ok) {
5024 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5025 file, linenum, args[0], args[1], args[cur_arg]);
5026 cur_arg += 1 + kw->skip ;
5027 err_code |= ERR_ALERT;
5028 continue;
5029 }
5030
5031 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5032 err_code |= code;
5033
5034 if (code) {
5035 if (err && *err) {
5036 indent_msg(&err, 2);
5037 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5038 }
5039 else
5040 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5041 file, linenum, args[0], args[1], args[cur_arg]);
5042 if (code & ERR_FATAL) {
5043 free(err);
5044 cur_arg += 1 + kw->skip;
5045 goto out;
5046 }
5047 }
5048 free(err);
5049 cur_arg += 1 + kw->skip;
5050 continue;
5051 }
5052
5053 err = NULL;
5054 if (!srv_dumped) {
5055 srv_dump_kws(&err);
5056 indent_msg(&err, 4);
5057 srv_dumped = 1;
5058 }
5059
5060 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5061 file, linenum, args[0], args[1], args[cur_arg],
5062 err ? " Registered keywords :" : "", err ? err : "");
5063 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005064
Willy Tarreau93893792009-07-23 13:19:11 +02005065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005067 }
5068 }
5069
Simon Horman8c3d0be2013-11-25 10:46:40 +09005070 /* Set initial drain state using now-configured weight */
5071 set_server_drain_state(newsrv);
5072
Willy Tarreaubaaee002006-06-26 02:48:02 +02005073 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005074 int ret;
5075
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005076 if (newsrv->trackit) {
5077 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5078 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_ALERT | ERR_FATAL;
5080 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005081 }
5082
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005083 /* If neither a port nor an addr was specified and no check transport
5084 * layer is forced, then the transport layer used by the checks is the
5085 * same as for the production traffic. Otherwise we use raw_sock by
5086 * default, unless one is specified.
5087 */
Simon Horman66183002013-02-23 10:16:43 +09005088 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005089#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005090 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02005091#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005092 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5093 }
Simon Horman66183002013-02-23 10:16:43 +09005094 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005095 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005096 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005097
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005098 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005099 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005100
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005101 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005102 /* not yet valid, because no port was set on
5103 * the server either. We'll check if we have
5104 * a known port on the first listener.
5105 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005106 struct listener *l;
5107
5108 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005109 newsrv->check.port = get_host_port(&l->addr);
5110 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005111 break;
5112 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005113 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005114 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5116 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02005117 err_code |= ERR_ALERT | ERR_FATAL;
5118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005119 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005120
Willy Tarreau2f075e92013-12-03 11:11:34 +01005121 /* note: check type will be set during the config review phase */
5122 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005123 if (ret) {
5124 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005125 goto out;
5126 }
5127
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005128 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 }
5130
Simon Hormand60d6912013-11-25 10:46:36 +09005131 if (do_agent) {
5132 int ret;
5133
5134 if (!newsrv->agent.port) {
5135 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5136 file, linenum, newsrv->id);
5137 err_code |= ERR_ALERT | ERR_FATAL;
5138 goto out;
5139 }
5140
5141 if (!newsrv->agent.inter)
5142 newsrv->agent.inter = newsrv->check.inter;
5143
5144 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5145 if (ret) {
5146 err_code |= ret;
5147 goto out;
5148 }
5149
Willy Tarreau33434322013-12-11 21:15:19 +01005150 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005151 }
5152
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005153 if (!defsrv) {
5154 if (newsrv->state & SRV_BACKUP)
5155 curproxy->srv_bck++;
5156 else
5157 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005158
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005159 newsrv->prev_state = newsrv->state;
5160 }
William Lallemanda73203e2012-03-12 12:48:57 +01005161 }
5162
5163 else if (strcmp(args[0], "unique-id-format") == 0) {
5164 if (!*(args[1])) {
5165 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5166 err_code |= ERR_ALERT | ERR_FATAL;
5167 goto out;
5168 }
William Lallemand3203ff42012-11-11 17:30:56 +01005169 if (*(args[2])) {
5170 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
5173 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005174 free(curproxy->conf.uniqueid_format_string);
5175 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005176
Willy Tarreau62a61232013-04-12 18:13:46 +02005177 free(curproxy->conf.uif_file);
5178 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5179 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005180 }
William Lallemanda73203e2012-03-12 12:48:57 +01005181
5182 else if (strcmp(args[0], "unique-id-header") == 0) {
5183 if (!*(args[1])) {
5184 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
5187 }
5188 free(curproxy->header_unique_id);
5189 curproxy->header_unique_id = strdup(args[1]);
5190 }
5191
William Lallemand723b73a2012-02-08 16:37:49 +01005192 else if (strcmp(args[0], "log-format") == 0) {
5193 if (!*(args[1])) {
5194 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5195 err_code |= ERR_ALERT | ERR_FATAL;
5196 goto out;
5197 }
William Lallemand3203ff42012-11-11 17:30:56 +01005198 if (*(args[2])) {
5199 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
5202 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005203
Willy Tarreau62a61232013-04-12 18:13:46 +02005204 if (curproxy->conf.logformat_string != default_http_log_format &&
5205 curproxy->conf.logformat_string != default_tcp_log_format &&
5206 curproxy->conf.logformat_string != clf_http_log_format)
5207 free(curproxy->conf.logformat_string);
5208 curproxy->conf.logformat_string = strdup(args[1]);
5209
5210 free(curproxy->conf.lfs_file);
5211 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5212 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005213
5214 /* get a chance to improve log-format error reporting by
5215 * reporting the correct line-number when possible.
5216 */
5217 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5218 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5219 file, linenum, curproxy->id);
5220 err_code |= ERR_WARN;
5221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
William Lallemand723b73a2012-02-08 16:37:49 +01005223
William Lallemand0f99e342011-10-12 17:50:54 +02005224 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5225 /* delete previous herited or defined syslog servers */
5226 struct logsrv *back;
5227
5228 if (*(args[1]) != 0) {
5229 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
5232 }
5233
William Lallemand723b73a2012-02-08 16:37:49 +01005234 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5235 LIST_DEL(&tmplogsrv->list);
5236 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005237 }
5238 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005239 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005240 struct logsrv *logsrv;
5241
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005243 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005244 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005245 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005246 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005247 LIST_INIT(&node->list);
5248 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005250 }
5251 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005252 struct sockaddr_storage *sk;
5253 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005254
5255 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256
William Lallemand0f99e342011-10-12 17:50:54 +02005257 logsrv->facility = get_log_facility(args[2]);
5258 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
5264
William Lallemand0f99e342011-10-12 17:50:54 +02005265 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005267 logsrv->level = get_log_level(args[3]);
5268 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
5274 }
5275
William Lallemand0f99e342011-10-12 17:50:54 +02005276 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005277 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005278 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005279 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005280 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005281 err_code |= ERR_ALERT | ERR_FATAL;
5282 goto out;
5283
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005284 }
5285 }
5286
Willy Tarreau902636f2013-03-10 19:44:48 +01005287 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005288 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005289 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005290 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005291 goto out;
5292 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005293
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005294 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005295
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005296 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005297 if (port1 != port2) {
5298 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5299 file, linenum, args[0], args[1]);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 }
5303
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005304 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005305 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
William Lallemand0f99e342011-10-12 17:50:54 +02005307
5308 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005309 }
5310 else {
5311 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5312 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 }
5316 }
5317 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005318 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005319 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005320 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005321 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005322
Willy Tarreau977b8e42006-12-29 14:19:17 +01005323 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005324 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005325
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005327 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5328 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005329 err_code |= ERR_ALERT | ERR_FATAL;
5330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005332
5333 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005334 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5335 free(curproxy->conn_src.iface_name);
5336 curproxy->conn_src.iface_name = NULL;
5337 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005338
Willy Tarreau902636f2013-03-10 19:44:48 +01005339 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005340 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005341 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005342 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005343 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005344 goto out;
5345 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005346
5347 proto = protocol_by_family(sk->ss_family);
5348 if (!proto || !proto->connect) {
5349 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005350 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005354
5355 if (port1 != port2) {
5356 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5357 file, linenum, args[0], args[1]);
5358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
5360 }
5361
Willy Tarreauef9a3602012-12-08 22:29:20 +01005362 curproxy->conn_src.source_addr = *sk;
5363 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005364
5365 cur_arg = 2;
5366 while (*(args[cur_arg])) {
5367 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005368#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5369#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005370 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005371 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5372 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005373 err_code |= ERR_ALERT | ERR_FATAL;
5374 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005375 }
5376#endif
5377 if (!*args[cur_arg + 1]) {
5378 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5379 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005382 }
5383
5384 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005385 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5386 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005387 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005388 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5389 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005390 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5391 char *name, *end;
5392
5393 name = args[cur_arg+1] + 7;
5394 while (isspace(*name))
5395 name++;
5396
5397 end = name;
5398 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5399 end++;
5400
Willy Tarreauef9a3602012-12-08 22:29:20 +01005401 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5402 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5403 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5404 curproxy->conn_src.bind_hdr_len = end - name;
5405 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5406 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5407 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005408
5409 /* now look for an occurrence number */
5410 while (isspace(*end))
5411 end++;
5412 if (*end == ',') {
5413 end++;
5414 name = end;
5415 if (*end == '-')
5416 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005417 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005418 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005419 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005420 }
5421
Willy Tarreauef9a3602012-12-08 22:29:20 +01005422 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005423 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5424 " occurrences values smaller than %d.\n",
5425 file, linenum, MAX_HDR_HISTORY);
5426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005429 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005430 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005431
Willy Tarreau902636f2013-03-10 19:44:48 +01005432 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005433 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005434 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005435 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005436 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005437 goto out;
5438 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005439
5440 proto = protocol_by_family(sk->ss_family);
5441 if (!proto || !proto->connect) {
5442 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5443 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005447
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005448 if (port1 != port2) {
5449 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5450 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005454 curproxy->conn_src.tproxy_addr = *sk;
5455 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005456 }
5457 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005458#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005459 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005460#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005461#else /* no TPROXY support */
5462 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005463 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005466#endif
5467 cur_arg += 2;
5468 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005469 }
5470
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005471 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5472#ifdef SO_BINDTODEVICE
5473 if (!*args[cur_arg + 1]) {
5474 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5475 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005478 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005479 free(curproxy->conn_src.iface_name);
5480 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5481 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005482 global.last_checks |= LSTCHK_NETADM;
5483#else
5484 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5485 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005488#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005489 cur_arg += 2;
5490 continue;
5491 }
5492 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005493 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005498 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5499 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5500 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005501 err_code |= ERR_ALERT | ERR_FATAL;
5502 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005505 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5507 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005511
5512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005513 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005514 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005516 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 }
5518 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005519 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005520 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005521 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005522 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005523 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 }
5525 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005526 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005527 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005528 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005529 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005530 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531 }
5532 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005533 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005534 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005535 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005536 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 }
5539 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005540 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005541 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005542 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005543 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005545 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005546 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005547 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005548 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005549 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005550 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005551 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005552 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005553 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005554 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005555 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005556 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005557 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005558 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005559 }
5560 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005561 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005562 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005563 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005564 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005565 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005567 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005568 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5570 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005573 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005574
5575 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005576 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005577 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005578 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 }
5581 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005582 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005583 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005584 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005585 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 }
5588 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005589 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005590 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005591 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005592 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
5595 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005596 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005597 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005598 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005599 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 }
5602 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005603 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005604 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005605 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005606 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005609 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005610 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005611 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005612 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005613 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005614 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005615 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005617 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005618
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 if (curproxy == &defproxy) {
5620 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005621 err_code |= ERR_ALERT | ERR_FATAL;
5622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005624 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005625 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 if (*(args[1]) == 0) {
5628 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005632
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005633 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005634 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5635 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5636 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
5639 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005640 err_code |= warnif_cond_conflicts(cond,
5641 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5642 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005643 }
5644 else if (*args[2]) {
5645 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5646 file, linenum, args[0], args[2]);
5647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
5650
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005651 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005652 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005653 wl->s = strdup(args[1]);
5654 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005655 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656 }
5657 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005658 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5660 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005661 err_code |= ERR_ALERT | ERR_FATAL;
5662 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005663 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005664
Willy Tarreauade5ec42010-01-28 19:33:49 +01005665 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005666 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005667 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005668 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005670 }
5671 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005672 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005673 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005674 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005675 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 }
5678 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005679 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005680 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005681 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005682 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 }
5685 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005686 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5688 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
5692
Willy Tarreauade5ec42010-01-28 19:33:49 +01005693 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005694 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005695 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005696 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 }
5699 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005700 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005701 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005702 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005703 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
5706 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005707 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005708 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005709 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005710 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 }
5713 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005714 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005715
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 if (curproxy == &defproxy) {
5717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005721 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005722 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 if (*(args[1]) == 0) {
5725 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005726 err_code |= ERR_ALERT | ERR_FATAL;
5727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005728 }
5729
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005730 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005731 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5732 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5733 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005734 err_code |= ERR_ALERT | ERR_FATAL;
5735 goto out;
5736 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005737 err_code |= warnif_cond_conflicts(cond,
5738 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5739 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005740 }
5741 else if (*args[2]) {
5742 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5743 file, linenum, args[0], args[2]);
5744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
5746 }
5747
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005748 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005749 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005750 wl->s = strdup(args[1]);
5751 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 }
5753 else if (!strcmp(args[0], "errorloc") ||
5754 !strcmp(args[0], "errorloc302") ||
5755 !strcmp(args[0], "errorloc303")) { /* error location */
5756 int errnum, errlen;
5757 char *err;
5758
Willy Tarreau977b8e42006-12-29 14:19:17 +01005759 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005760 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005761
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005763 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 }
5767
5768 errnum = atol(args[1]);
5769 if (!strcmp(args[0], "errorloc303")) {
5770 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5771 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5772 } else {
5773 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5774 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5775 }
5776
Willy Tarreau0f772532006-12-23 20:51:41 +01005777 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5778 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005779 chunk_destroy(&curproxy->errmsg[rc]);
5780 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005781 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005783 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005784
5785 if (rc >= HTTP_ERR_SIZE) {
5786 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5787 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 free(err);
5789 }
5790 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005791 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5792 int errnum, errlen, fd;
5793 char *err;
5794 struct stat stat;
5795
5796 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005797 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005798
5799 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005800 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005801 err_code |= ERR_ALERT | ERR_FATAL;
5802 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005803 }
5804
5805 fd = open(args[2], O_RDONLY);
5806 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5807 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5808 file, linenum, args[2], args[1]);
5809 if (fd >= 0)
5810 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005811 err_code |= ERR_ALERT | ERR_FATAL;
5812 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005813 }
5814
Willy Tarreau27a674e2009-08-17 07:23:33 +02005815 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005816 errlen = stat.st_size;
5817 } else {
5818 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005819 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005820 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005821 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005822 }
5823
5824 err = malloc(errlen); /* malloc() must succeed during parsing */
5825 errnum = read(fd, err, errlen);
5826 if (errnum != errlen) {
5827 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5828 file, linenum, args[2], args[1]);
5829 close(fd);
5830 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005831 err_code |= ERR_ALERT | ERR_FATAL;
5832 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005833 }
5834 close(fd);
5835
5836 errnum = atol(args[1]);
5837 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5838 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005839 chunk_destroy(&curproxy->errmsg[rc]);
5840 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005841 break;
5842 }
5843 }
5844
5845 if (rc >= HTTP_ERR_SIZE) {
5846 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5847 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005848 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005849 free(err);
5850 }
5851 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005852 else if (!strcmp(args[0], "compression")) {
5853 struct comp *comp;
5854 if (curproxy->comp == NULL) {
5855 comp = calloc(1, sizeof(struct comp));
5856 curproxy->comp = comp;
5857 } else {
5858 comp = curproxy->comp;
5859 }
5860
5861 if (!strcmp(args[1], "algo")) {
5862 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005863 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005864
William Lallemand82fe75c2012-10-23 10:25:10 +02005865 cur_arg = 2;
5866 if (!*args[cur_arg]) {
5867 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5868 file, linenum, args[0]);
5869 err_code |= ERR_ALERT | ERR_FATAL;
5870 goto out;
5871 }
5872 while (*(args[cur_arg])) {
5873 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5874 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5875 file, linenum, args[0], args[cur_arg]);
5876 err_code |= ERR_ALERT | ERR_FATAL;
5877 goto out;
5878 }
William Lallemand552df672012-11-07 13:21:47 +01005879 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5880 curproxy->comp->algos->end(&ctx);
5881 } else {
5882 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5883 file, linenum, args[0], args[cur_arg]);
5884 err_code |= ERR_ALERT | ERR_FATAL;
5885 goto out;
5886 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005887 cur_arg ++;
5888 continue;
5889 }
5890 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005891 else if (!strcmp(args[1], "offload")) {
5892 comp->offload = 1;
5893 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005894 else if (!strcmp(args[1], "type")) {
5895 int cur_arg;
5896 cur_arg = 2;
5897 if (!*args[cur_arg]) {
5898 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5899 file, linenum, args[0]);
5900 err_code |= ERR_ALERT | ERR_FATAL;
5901 goto out;
5902 }
5903 while (*(args[cur_arg])) {
5904 comp_append_type(comp, args[cur_arg]);
5905 cur_arg ++;
5906 continue;
5907 }
5908 }
5909 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005910 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005911 file, linenum, args[0]);
5912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
5914 }
5915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005917 struct cfg_kw_list *kwl;
5918 int index;
5919
5920 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5921 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5922 if (kwl->kw[index].section != CFG_LISTEN)
5923 continue;
5924 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5925 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005926 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005927 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005928 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005929 err_code |= ERR_ALERT | ERR_FATAL;
5930 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005931 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005932 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005933 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005934 err_code |= ERR_WARN;
5935 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005936 }
Willy Tarreau93893792009-07-23 13:19:11 +02005937 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005938 }
5939 }
5940 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005941
Willy Tarreau6daf3432008-01-22 16:44:08 +01005942 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005943 err_code |= ERR_ALERT | ERR_FATAL;
5944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945 }
Willy Tarreau93893792009-07-23 13:19:11 +02005946 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005947 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005948 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949}
5950
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005951int
5952cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5953{
5954
5955 int err_code = 0;
5956 const char *err;
5957
5958 if (!strcmp(args[0], "userlist")) { /* new userlist */
5959 struct userlist *newul;
5960
5961 if (!*args[1]) {
5962 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5963 file, linenum, args[0]);
5964 err_code |= ERR_ALERT | ERR_FATAL;
5965 goto out;
5966 }
5967
5968 err = invalid_char(args[1]);
5969 if (err) {
5970 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5971 file, linenum, *err, args[0], args[1]);
5972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
5975
5976 for (newul = userlist; newul; newul = newul->next)
5977 if (!strcmp(newul->name, args[1])) {
5978 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5979 file, linenum, args[1]);
5980 err_code |= ERR_WARN;
5981 goto out;
5982 }
5983
5984 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5985 if (!newul) {
5986 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5987 err_code |= ERR_ALERT | ERR_ABORT;
5988 goto out;
5989 }
5990
5991 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5992 newul->name = strdup(args[1]);
5993
5994 if (!newul->groupusers | !newul->name) {
5995 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5996 err_code |= ERR_ALERT | ERR_ABORT;
5997 goto out;
5998 }
5999
6000 newul->next = userlist;
6001 userlist = newul;
6002
6003 } else if (!strcmp(args[0], "group")) { /* new group */
6004 int cur_arg, i;
6005 const char *err;
6006
6007 if (!*args[1]) {
6008 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6009 file, linenum, args[0]);
6010 err_code |= ERR_ALERT | ERR_FATAL;
6011 goto out;
6012 }
6013
6014 err = invalid_char(args[1]);
6015 if (err) {
6016 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6017 file, linenum, *err, args[0], args[1]);
6018 err_code |= ERR_ALERT | ERR_FATAL;
6019 goto out;
6020 }
6021
6022 for(i = 0; i < userlist->grpcnt; i++)
6023 if (!strcmp(userlist->groups[i], args[1])) {
6024 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6025 file, linenum, args[1], userlist->name);
6026 err_code |= ERR_ALERT;
6027 goto out;
6028 }
6029
6030 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6031 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6032 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6033 err_code |= ERR_ALERT | ERR_FATAL;
6034 goto out;
6035 }
6036
6037 cur_arg = 2;
6038
6039 while (*args[cur_arg]) {
6040 if (!strcmp(args[cur_arg], "users")) {
6041 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6042 cur_arg += 2;
6043 continue;
6044 } else {
6045 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6046 file, linenum, args[0]);
6047 err_code |= ERR_ALERT | ERR_FATAL;
6048 goto out;
6049 }
6050 }
6051
6052 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6053 } else if (!strcmp(args[0], "user")) { /* new user */
6054 struct auth_users *newuser;
6055 int cur_arg;
6056
6057 if (!*args[1]) {
6058 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6059 file, linenum, args[0]);
6060 err_code |= ERR_ALERT | ERR_FATAL;
6061 goto out;
6062 }
6063
6064 for (newuser = userlist->users; newuser; newuser = newuser->next)
6065 if (!strcmp(newuser->user, args[1])) {
6066 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6067 file, linenum, args[1], userlist->name);
6068 err_code |= ERR_ALERT;
6069 goto out;
6070 }
6071
6072 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6073 if (!newuser) {
6074 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6075 err_code |= ERR_ALERT | ERR_ABORT;
6076 goto out;
6077 }
6078
6079 newuser->user = strdup(args[1]);
6080
6081 newuser->next = userlist->users;
6082 userlist->users = newuser;
6083
6084 cur_arg = 2;
6085
6086 while (*args[cur_arg]) {
6087 if (!strcmp(args[cur_arg], "password")) {
6088#ifndef CONFIG_HAP_CRYPT
6089 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6090 file, linenum);
6091 err_code |= ERR_ALERT;
6092#endif
6093 newuser->pass = strdup(args[cur_arg + 1]);
6094 cur_arg += 2;
6095 continue;
6096 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6097 newuser->pass = strdup(args[cur_arg + 1]);
6098 newuser->flags |= AU_O_INSECURE;
6099 cur_arg += 2;
6100 continue;
6101 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006102 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006103 cur_arg += 2;
6104 continue;
6105 } else {
6106 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6107 file, linenum, args[0]);
6108 err_code |= ERR_ALERT | ERR_FATAL;
6109 goto out;
6110 }
6111 }
6112 } else {
6113 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6114 err_code |= ERR_ALERT | ERR_FATAL;
6115 }
6116
6117out:
6118 return err_code;
6119}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120
6121/*
6122 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006123 * Returns the error code, 0 if OK, or any combination of :
6124 * - ERR_ABORT: must abort ASAP
6125 * - ERR_FATAL: we can continue parsing but not start the service
6126 * - ERR_WARN: a warning has been emitted
6127 * - ERR_ALERT: an alert has been emitted
6128 * Only the two first ones can stop processing, the two others are just
6129 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006130 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006131int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006132{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006133 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134 FILE *f;
6135 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006136 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006137 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006138
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 if ((f=fopen(file,"r")) == NULL)
6140 return -1;
6141
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006142 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006143 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006144 char *end;
6145 char *args[MAX_LINE_ARGS + 1];
6146 char *line = thisline;
6147
Willy Tarreaubaaee002006-06-26 02:48:02 +02006148 linenum++;
6149
6150 end = line + strlen(line);
6151
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006152 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6153 /* Check if we reached the limit and the last char is not \n.
6154 * Watch out for the last line without the terminating '\n'!
6155 */
6156 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006157 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006158 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006159 }
6160
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006162 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006163 line++;
6164
6165 arg = 0;
6166 args[arg] = line;
6167
6168 while (*line && arg < MAX_LINE_ARGS) {
6169 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6170 * C equivalent value. Other combinations left unchanged (eg: \1).
6171 */
6172 if (*line == '\\') {
6173 int skip = 0;
6174 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6175 *line = line[1];
6176 skip = 1;
6177 }
6178 else if (line[1] == 'r') {
6179 *line = '\r';
6180 skip = 1;
6181 }
6182 else if (line[1] == 'n') {
6183 *line = '\n';
6184 skip = 1;
6185 }
6186 else if (line[1] == 't') {
6187 *line = '\t';
6188 skip = 1;
6189 }
6190 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006191 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192 unsigned char hex1, hex2;
6193 hex1 = toupper(line[2]) - '0';
6194 hex2 = toupper(line[3]) - '0';
6195 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6196 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6197 *line = (hex1<<4) + hex2;
6198 skip = 3;
6199 }
6200 else {
6201 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006202 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 }
6204 }
6205 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006206 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 end -= skip;
6208 }
6209 line++;
6210 }
6211 else if (*line == '#' || *line == '\n' || *line == '\r') {
6212 /* end of string, end of loop */
6213 *line = 0;
6214 break;
6215 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006216 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006218 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006219 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006220 line++;
6221 args[++arg] = line;
6222 }
6223 else {
6224 line++;
6225 }
6226 }
6227
6228 /* empty line */
6229 if (!**args)
6230 continue;
6231
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006232 if (*line) {
6233 /* we had to stop due to too many args.
6234 * Let's terminate the string, print the offending part then cut the
6235 * last arg.
6236 */
6237 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6238 line++;
6239 *line = '\0';
6240
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006241 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006242 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006243 err_code |= ERR_ALERT | ERR_FATAL;
6244 args[arg] = line;
6245 }
6246
Willy Tarreau540abe42007-05-02 20:50:16 +02006247 /* zero out remaining args and ensure that at least one entry
6248 * is zeroed out.
6249 */
6250 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251 args[arg] = line;
6252 }
6253
Willy Tarreau3842f002009-06-14 11:39:52 +02006254 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006255 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006256 char *tmp;
6257
Willy Tarreau3842f002009-06-14 11:39:52 +02006258 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006259 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006260 for (arg=0; *args[arg+1]; arg++)
6261 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006262 *tmp = '\0'; // fix the next arg to \0
6263 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006264 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006265 else if (!strcmp(args[0], "default")) {
6266 kwm = KWM_DEF;
6267 for (arg=0; *args[arg+1]; arg++)
6268 args[arg] = args[arg+1]; // shift args after inversion
6269 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006270
William Lallemand0f99e342011-10-12 17:50:54 +02006271 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6272 strcmp(args[0], "log") != 0) {
6273 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006274 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006275 }
6276
Willy Tarreau977b8e42006-12-29 14:19:17 +01006277 if (!strcmp(args[0], "listen") ||
6278 !strcmp(args[0], "frontend") ||
6279 !strcmp(args[0], "backend") ||
6280 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006281 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006282 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006283 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006284 cursection = strdup(args[0]);
6285 }
6286 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006288 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006289 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006290 }
6291 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006292 confsect = CFG_USERLIST;
6293 free(cursection);
6294 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006295 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006296 else if (!strcmp(args[0], "peers")) {
6297 confsect = CFG_PEERS;
6298 free(cursection);
6299 cursection = strdup(args[0]);
6300 }
6301
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 /* else it's a section keyword */
6303
6304 switch (confsect) {
6305 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006306 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006307 break;
6308 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006309 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006310 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006311 case CFG_USERLIST:
6312 err_code |= cfg_parse_users(file, linenum, args, kwm);
6313 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006314 case CFG_PEERS:
6315 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6316 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006317 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006318 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006319 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006320 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006321
6322 if (err_code & ERR_ABORT)
6323 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006325 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006326 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006327 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006328 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006329}
6330
Willy Tarreaubb925012009-07-23 13:36:36 +02006331/*
6332 * Returns the error code, 0 if OK, or any combination of :
6333 * - ERR_ABORT: must abort ASAP
6334 * - ERR_FATAL: we can continue parsing but not start the service
6335 * - ERR_WARN: a warning has been emitted
6336 * - ERR_ALERT: an alert has been emitted
6337 * Only the two first ones can stop processing, the two others are just
6338 * indicators.
6339 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006340int check_config_validity()
6341{
6342 int cfgerr = 0;
6343 struct proxy *curproxy = NULL;
6344 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006345 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006346 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006347 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006348 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006350 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 /*
6352 * Now, check for the integrity of all that we have collected.
6353 */
6354
6355 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006356 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357
Willy Tarreau193b8c62012-11-22 00:17:38 +01006358 if (!global.tune.max_http_hdr)
6359 global.tune.max_http_hdr = MAX_HTTP_HDR;
6360
6361 if (!global.tune.cookie_len)
6362 global.tune.cookie_len = CAPTURE_LEN;
6363
6364 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6365
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006366 /* first, we will invert the proxy list order */
6367 curproxy = NULL;
6368 while (proxy) {
6369 struct proxy *next;
6370
6371 next = proxy->next;
6372 proxy->next = curproxy;
6373 curproxy = proxy;
6374 if (!next)
6375 break;
6376 proxy = next;
6377 }
6378
Willy Tarreaubaaee002006-06-26 02:48:02 +02006379 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006380 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006381 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006382 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006383 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006384 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006385 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006386 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006387
Willy Tarreau050536d2012-10-04 08:47:34 +02006388 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006389 /* proxy ID not set, use automatic numbering with first
6390 * spare entry starting with next_pxid.
6391 */
6392 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6393 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6394 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006395 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006396 next_pxid++;
6397
Willy Tarreau55ea7572007-06-17 19:56:27 +02006398
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006400 /* ensure we don't keep listeners uselessly bound */
6401 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 curproxy = curproxy->next;
6403 continue;
6404 }
6405
Willy Tarreau16a21472012-11-19 12:39:59 +01006406 /* number of processes this proxy is bound to */
6407 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6408
Willy Tarreauff01a212009-03-15 13:46:16 +01006409 switch (curproxy->mode) {
6410 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006411 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006412 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006413 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6414 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006415 cfgerr++;
6416 }
6417
6418 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006419 Warning("config : servers will be ignored for %s '%s'.\n",
6420 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006421 break;
6422
6423 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006424 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006425 break;
6426
6427 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006428 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006429 break;
6430 }
6431
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006432 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006433 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006434 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006435 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6436 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006437 cfgerr++;
6438 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006439#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006440 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006441 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6442 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006443 cfgerr++;
6444 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006446 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006447 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6448 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006449 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006450 }
6451 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006452 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006453 /* If no LB algo is set in a backend, and we're not in
6454 * transparent mode, dispatch mode nor proxy mode, we
6455 * want to use balance roundrobin by default.
6456 */
6457 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6458 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459 }
6460 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006461
Willy Tarreau1620ec32011-08-06 17:05:02 +02006462 if (curproxy->options & PR_O_DISPATCH)
6463 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6464 else if (curproxy->options & PR_O_HTTP_PROXY)
6465 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6466 else if (curproxy->options & PR_O_TRANSP)
6467 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006468
Willy Tarreau1620ec32011-08-06 17:05:02 +02006469 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6470 if (curproxy->options & PR_O_DISABLE404) {
6471 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6472 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6473 err_code |= ERR_WARN;
6474 curproxy->options &= ~PR_O_DISABLE404;
6475 }
6476 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6477 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6478 "send-state", proxy_type_str(curproxy), curproxy->id);
6479 err_code |= ERR_WARN;
6480 curproxy->options &= ~PR_O2_CHK_SNDST;
6481 }
Willy Tarreauef781042010-01-27 11:53:01 +01006482 }
6483
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006484 /* if a default backend was specified, let's find it */
6485 if (curproxy->defbe.name) {
6486 struct proxy *target;
6487
Alex Williams96532db2009-11-01 21:27:13 -05006488 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006489 if (!target) {
6490 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6491 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006492 cfgerr++;
6493 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006494 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6495 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006496 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006497 } else {
6498 free(curproxy->defbe.name);
6499 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006500 /* we force the backend to be present on at least all of
6501 * the frontend's processes.
6502 */
6503 target->bind_proc = curproxy->bind_proc ?
6504 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006505
6506 /* Emit a warning if this proxy also has some servers */
6507 if (curproxy->srv) {
6508 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6509 curproxy->id);
6510 err_code |= ERR_WARN;
6511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 }
6513 }
6514
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006515 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006516 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6517 /* map jump target for ACT_SETBE in req_rep chain */
6518 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006519 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006520 struct proxy *target;
6521
Willy Tarreaua496b602006-12-17 23:15:24 +01006522 if (exp->action != ACT_SETBE)
6523 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006524
Alex Williams96532db2009-11-01 21:27:13 -05006525 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006526 if (!target) {
6527 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6528 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006529 cfgerr++;
6530 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006531 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6532 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006533 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006534 } else {
6535 free((void *)exp->replace);
6536 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006537 /* we force the backend to be present on at least all of
6538 * the frontend's processes.
6539 */
6540 target->bind_proc = curproxy->bind_proc ?
6541 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006542 }
6543 }
6544 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006545
6546 /* find the target proxy for 'use_backend' rules */
6547 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006548 struct proxy *target;
6549
Alex Williams96532db2009-11-01 21:27:13 -05006550 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006551
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006552 if (!target) {
6553 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6554 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006555 cfgerr++;
6556 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006557 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6558 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006559 cfgerr++;
6560 } else {
6561 free((void *)rule->be.name);
6562 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006563 /* we force the backend to be present on at least all of
6564 * the frontend's processes.
6565 */
6566 target->bind_proc = curproxy->bind_proc ?
6567 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006568 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006569 }
6570
6571 /* find the target proxy for 'use_backend' rules */
6572 list_for_each_entry(srule, &curproxy->server_rules, list) {
6573 struct server *target = findserver(curproxy, srule->srv.name);
6574
6575 if (!target) {
6576 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6577 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6578 cfgerr++;
6579 continue;
6580 }
6581 free((void *)srule->srv.name);
6582 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006583 }
6584
Emeric Brunb982a3d2010-01-04 15:45:53 +01006585 /* find the target table for 'stick' rules */
6586 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6587 struct proxy *target;
6588
Emeric Brun1d33b292010-01-04 15:47:17 +01006589 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6590 if (mrule->flags & STK_IS_STORE)
6591 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6592
Emeric Brunb982a3d2010-01-04 15:45:53 +01006593 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006594 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006595 else
6596 target = curproxy;
6597
6598 if (!target) {
6599 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6600 curproxy->id, mrule->table.name);
6601 cfgerr++;
6602 }
6603 else if (target->table.size == 0) {
6604 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6605 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6606 cfgerr++;
6607 }
Willy Tarreau12785782012-04-27 21:37:17 +02006608 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6609 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006610 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6611 cfgerr++;
6612 }
6613 else {
6614 free((void *)mrule->table.name);
6615 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006616 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006617 }
6618 }
6619
6620 /* find the target table for 'store response' rules */
6621 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6622 struct proxy *target;
6623
Emeric Brun1d33b292010-01-04 15:47:17 +01006624 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6625
Emeric Brunb982a3d2010-01-04 15:45:53 +01006626 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006627 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006628 else
6629 target = curproxy;
6630
6631 if (!target) {
6632 Alert("Proxy '%s': unable to find store table '%s'.\n",
6633 curproxy->id, mrule->table.name);
6634 cfgerr++;
6635 }
6636 else if (target->table.size == 0) {
6637 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6638 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6639 cfgerr++;
6640 }
Willy Tarreau12785782012-04-27 21:37:17 +02006641 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6642 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006643 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6644 cfgerr++;
6645 }
6646 else {
6647 free((void *)mrule->table.name);
6648 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006649 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006650 }
6651 }
6652
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006653 /* find the target table for 'tcp-request' layer 4 rules */
6654 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6655 struct proxy *target;
6656
Willy Tarreaub4c84932013-07-23 19:15:30 +02006657 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006658 continue;
6659
6660 if (trule->act_prm.trk_ctr.table.n)
6661 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6662 else
6663 target = curproxy;
6664
6665 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006666 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6667 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006668 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006669 cfgerr++;
6670 }
6671 else if (target->table.size == 0) {
6672 Alert("Proxy '%s': table '%s' used but not configured.\n",
6673 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6674 cfgerr++;
6675 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006676 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6677 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6678 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006679 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006680 cfgerr++;
6681 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006682 else {
6683 free(trule->act_prm.trk_ctr.table.n);
6684 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006685 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006686 * to pass a list of counters to track and allocate them right here using
6687 * stktable_alloc_data_type().
6688 */
6689 }
6690 }
6691
Willy Tarreaud1f96522010-08-03 19:34:32 +02006692 /* find the target table for 'tcp-request' layer 6 rules */
6693 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6694 struct proxy *target;
6695
Willy Tarreaub4c84932013-07-23 19:15:30 +02006696 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006697 continue;
6698
6699 if (trule->act_prm.trk_ctr.table.n)
6700 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6701 else
6702 target = curproxy;
6703
6704 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006705 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6706 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006707 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006708 cfgerr++;
6709 }
6710 else if (target->table.size == 0) {
6711 Alert("Proxy '%s': table '%s' used but not configured.\n",
6712 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6713 cfgerr++;
6714 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006715 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6716 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6717 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006718 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006719 cfgerr++;
6720 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006721 else {
6722 free(trule->act_prm.trk_ctr.table.n);
6723 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006724 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006725 * to pass a list of counters to track and allocate them right here using
6726 * stktable_alloc_data_type().
6727 */
6728 }
6729 }
6730
Emeric Brun32da3c42010-09-23 18:39:19 +02006731 if (curproxy->table.peers.name) {
6732 struct peers *curpeers = peers;
6733
6734 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6735 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6736 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006737 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006738 break;
6739 }
6740 }
6741
6742 if (!curpeers) {
6743 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6744 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006745 free((void *)curproxy->table.peers.name);
6746 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006747 cfgerr++;
6748 }
6749 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006750 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6751 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006752 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006753 cfgerr++;
6754 }
6755 }
6756
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006757 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006758 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006759 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6760 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6761 "proxy", curproxy->id);
6762 cfgerr++;
6763 goto out_uri_auth_compat;
6764 }
6765
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006766 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006767 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006768 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006769 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006770
Willy Tarreau95fa4692010-02-01 13:05:50 +01006771 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6772 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006773
6774 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006775 uri_auth_compat_req[i++] = "realm";
6776 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6777 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006778
Willy Tarreau95fa4692010-02-01 13:05:50 +01006779 uri_auth_compat_req[i++] = "unless";
6780 uri_auth_compat_req[i++] = "{";
6781 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6782 uri_auth_compat_req[i++] = "}";
6783 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006784
Willy Tarreauff011f22011-01-06 17:51:27 +01006785 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6786 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006787 cfgerr++;
6788 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006789 }
6790
Willy Tarreauff011f22011-01-06 17:51:27 +01006791 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006792
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006793 if (curproxy->uri_auth->auth_realm) {
6794 free(curproxy->uri_auth->auth_realm);
6795 curproxy->uri_auth->auth_realm = NULL;
6796 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006797
6798 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006799 }
6800out_uri_auth_compat:
6801
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006802 /* compile the log format */
6803 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006804 if (curproxy->conf.logformat_string != default_http_log_format &&
6805 curproxy->conf.logformat_string != default_tcp_log_format &&
6806 curproxy->conf.logformat_string != clf_http_log_format)
6807 free(curproxy->conf.logformat_string);
6808 curproxy->conf.logformat_string = NULL;
6809 free(curproxy->conf.lfs_file);
6810 curproxy->conf.lfs_file = NULL;
6811 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006812 }
6813
Willy Tarreau62a61232013-04-12 18:13:46 +02006814 if (curproxy->conf.logformat_string) {
6815 curproxy->conf.args.ctx = ARGC_LOG;
6816 curproxy->conf.args.file = curproxy->conf.lfs_file;
6817 curproxy->conf.args.line = curproxy->conf.lfs_line;
6818 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006819 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006820 curproxy->conf.args.file = NULL;
6821 curproxy->conf.args.line = 0;
6822 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006823
Willy Tarreau62a61232013-04-12 18:13:46 +02006824 if (curproxy->conf.uniqueid_format_string) {
6825 curproxy->conf.args.ctx = ARGC_UIF;
6826 curproxy->conf.args.file = curproxy->conf.uif_file;
6827 curproxy->conf.args.line = curproxy->conf.uif_line;
6828 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006829 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006830 curproxy->conf.args.file = NULL;
6831 curproxy->conf.args.line = 0;
6832 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006833
6834 /* only now we can check if some args remain unresolved */
6835 cfgerr += smp_resolve_args(curproxy);
6836 if (!cfgerr)
6837 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006838
Willy Tarreau2738a142006-07-08 17:28:09 +02006839 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006840 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006841 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006842 (!curproxy->timeout.connect ||
6843 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006844 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006845 " | While not properly invalid, you will certainly encounter various problems\n"
6846 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006847 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006848 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006849 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006850 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006851
Willy Tarreau1fa31262007-12-03 00:36:16 +01006852 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6853 * We must still support older configurations, so let's find out whether those
6854 * parameters have been set or must be copied from contimeouts.
6855 */
6856 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006857 if (!curproxy->timeout.tarpit ||
6858 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006859 /* tarpit timeout not set. We search in the following order:
6860 * default.tarpit, curr.connect, default.connect.
6861 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006862 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006863 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006864 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006865 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006866 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006867 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006868 }
6869 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006870 (!curproxy->timeout.queue ||
6871 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006872 /* queue timeout not set. We search in the following order:
6873 * default.queue, curr.connect, default.connect.
6874 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006875 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006876 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006877 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006878 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006879 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006880 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006881 }
6882 }
6883
Willy Tarreau1620ec32011-08-06 17:05:02 +02006884 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006885 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6886 curproxy->check_req = (char *)malloc(curproxy->check_len);
6887 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006888 }
6889
Willy Tarreau193b8c62012-11-22 00:17:38 +01006890 /* ensure that cookie capture length is not too large */
6891 if (curproxy->capture_len >= global.tune.cookie_len) {
6892 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6893 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6894 err_code |= ERR_WARN;
6895 curproxy->capture_len = global.tune.cookie_len - 1;
6896 }
6897
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006898 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006899 if (curproxy->nb_req_cap) {
6900 if (curproxy->mode == PR_MODE_HTTP) {
6901 curproxy->req_cap_pool = create_pool("ptrcap",
6902 curproxy->nb_req_cap * sizeof(char *),
6903 MEM_F_SHARED);
6904 } else {
6905 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6906 proxy_type_str(curproxy), curproxy->id);
6907 err_code |= ERR_WARN;
6908 curproxy->to_log &= ~LW_REQHDR;
6909 curproxy->nb_req_cap = 0;
6910 }
6911 }
6912
6913 if (curproxy->nb_rsp_cap) {
6914 if (curproxy->mode == PR_MODE_HTTP) {
6915 curproxy->rsp_cap_pool = create_pool("ptrcap",
6916 curproxy->nb_rsp_cap * sizeof(char *),
6917 MEM_F_SHARED);
6918 } else {
6919 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6920 proxy_type_str(curproxy), curproxy->id);
6921 err_code |= ERR_WARN;
6922 curproxy->to_log &= ~LW_REQHDR;
6923 curproxy->nb_rsp_cap = 0;
6924 }
6925 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006926
Willy Tarreaubaaee002006-06-26 02:48:02 +02006927 /* first, we will invert the servers list order */
6928 newsrv = NULL;
6929 while (curproxy->srv) {
6930 struct server *next;
6931
6932 next = curproxy->srv->next;
6933 curproxy->srv->next = newsrv;
6934 newsrv = curproxy->srv;
6935 if (!next)
6936 break;
6937 curproxy->srv = next;
6938 }
6939
Willy Tarreaudd701652010-05-25 23:03:02 +02006940 /* assign automatic UIDs to servers which don't have one yet */
6941 next_id = 1;
6942 newsrv = curproxy->srv;
6943 while (newsrv != NULL) {
6944 if (!newsrv->puid) {
6945 /* server ID not set, use automatic numbering with first
6946 * spare entry starting with next_svid.
6947 */
6948 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6949 newsrv->conf.id.key = newsrv->puid = next_id;
6950 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6951 }
6952 next_id++;
6953 newsrv = newsrv->next;
6954 }
6955
Willy Tarreau20697042007-11-15 23:26:18 +01006956 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006957 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006958
Willy Tarreau62c3be22012-01-20 13:12:32 +01006959 /*
6960 * If this server supports a maxconn parameter, it needs a dedicated
6961 * tasks to fill the emptied slots when a connection leaves.
6962 * Also, resolve deferred tracking dependency if needed.
6963 */
6964 newsrv = curproxy->srv;
6965 while (newsrv != NULL) {
6966 if (newsrv->minconn > newsrv->maxconn) {
6967 /* Only 'minconn' was specified, or it was higher than or equal
6968 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6969 * this will avoid further useless expensive computations.
6970 */
6971 newsrv->maxconn = newsrv->minconn;
6972 } else if (newsrv->maxconn && !newsrv->minconn) {
6973 /* minconn was not specified, so we set it to maxconn */
6974 newsrv->minconn = newsrv->maxconn;
6975 }
6976
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006977#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006978 if (newsrv->use_ssl || newsrv->check.use_ssl)
6979 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006980#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006981
Willy Tarreau2f075e92013-12-03 11:11:34 +01006982 /* set the check type on the server */
6983 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6984
Willy Tarreau62c3be22012-01-20 13:12:32 +01006985 if (newsrv->trackit) {
6986 struct proxy *px;
6987 struct server *srv;
6988 char *pname, *sname;
6989
6990 pname = newsrv->trackit;
6991 sname = strrchr(pname, '/');
6992
6993 if (sname)
6994 *sname++ = '\0';
6995 else {
6996 sname = pname;
6997 pname = NULL;
6998 }
6999
7000 if (pname) {
7001 px = findproxy(pname, PR_CAP_BE);
7002 if (!px) {
7003 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7004 proxy_type_str(curproxy), curproxy->id,
7005 newsrv->id, pname);
7006 cfgerr++;
7007 goto next_srv;
7008 }
7009 } else
7010 px = curproxy;
7011
7012 srv = findserver(px, sname);
7013 if (!srv) {
7014 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7015 proxy_type_str(curproxy), curproxy->id,
7016 newsrv->id, sname);
7017 cfgerr++;
7018 goto next_srv;
7019 }
7020
Willy Tarreauff5ae352013-12-11 20:36:34 +01007021 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007022 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7023 "tracking as it does not have checks enabled.\n",
7024 proxy_type_str(curproxy), curproxy->id,
7025 newsrv->id, px->id, srv->id);
7026 cfgerr++;
7027 goto next_srv;
7028 }
7029
7030 if (curproxy != px &&
7031 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7032 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7033 "tracking: disable-on-404 option inconsistency.\n",
7034 proxy_type_str(curproxy), curproxy->id,
7035 newsrv->id, px->id, srv->id);
7036 cfgerr++;
7037 goto next_srv;
7038 }
7039
7040 /* if the other server is forced disabled, we have to do the same here */
7041 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007042 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007043 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007044 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007045 }
7046
7047 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007048 newsrv->tracknext = srv->trackers;
7049 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007050
7051 free(newsrv->trackit);
7052 newsrv->trackit = NULL;
7053 }
7054 next_srv:
7055 newsrv = newsrv->next;
7056 }
7057
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007058 /* We have to initialize the server lookup mechanism depending
7059 * on what LB algorithm was choosen.
7060 */
7061
7062 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7063 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7064 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007065 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7066 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7067 init_server_map(curproxy);
7068 } else {
7069 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7070 fwrr_init_server_groups(curproxy);
7071 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007072 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007073
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007074 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007075 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7076 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7077 fwlc_init_server_tree(curproxy);
7078 } else {
7079 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7080 fas_init_server_tree(curproxy);
7081 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007082 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007083
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007084 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007085 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7086 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7087 chash_init_server_tree(curproxy);
7088 } else {
7089 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7090 init_server_map(curproxy);
7091 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007092 break;
7093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007094
7095 if (curproxy->options & PR_O_LOGASAP)
7096 curproxy->to_log &= ~LW_BYTES;
7097
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007098 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007099 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007100 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7101 proxy_type_str(curproxy), curproxy->id);
7102 err_code |= ERR_WARN;
7103 }
7104
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007105 if (curproxy->mode != PR_MODE_HTTP) {
7106 int optnum;
7107
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007108 if (curproxy->uri_auth) {
7109 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7110 proxy_type_str(curproxy), curproxy->id);
7111 err_code |= ERR_WARN;
7112 curproxy->uri_auth = NULL;
7113 }
7114
Willy Tarreau87cf5142011-08-19 22:57:24 +02007115 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007116 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7117 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7118 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007119 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007120 }
7121
7122 if (curproxy->options & PR_O_ORGTO) {
7123 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7124 "originalto", proxy_type_str(curproxy), curproxy->id);
7125 err_code |= ERR_WARN;
7126 curproxy->options &= ~PR_O_ORGTO;
7127 }
7128
7129 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7130 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7131 (curproxy->cap & cfg_opts[optnum].cap) &&
7132 (curproxy->options & cfg_opts[optnum].val)) {
7133 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7134 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7135 err_code |= ERR_WARN;
7136 curproxy->options &= ~cfg_opts[optnum].val;
7137 }
7138 }
7139
7140 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7141 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7142 (curproxy->cap & cfg_opts2[optnum].cap) &&
7143 (curproxy->options2 & cfg_opts2[optnum].val)) {
7144 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7145 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7146 err_code |= ERR_WARN;
7147 curproxy->options2 &= ~cfg_opts2[optnum].val;
7148 }
7149 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007150
Pieter Baauwd551fb52013-05-08 22:49:23 +02007151#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007152 if (curproxy->conn_src.bind_hdr_occ) {
7153 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007154 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007155 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007156 err_code |= ERR_WARN;
7157 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007158#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007159 }
7160
Willy Tarreaubaaee002006-06-26 02:48:02 +02007161 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007162 * ensure that we're not cross-dressing a TCP server into HTTP.
7163 */
7164 newsrv = curproxy->srv;
7165 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007166 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007167 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7168 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007169 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007170 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007171
Willy Tarreau0cec3312011-10-31 13:49:26 +01007172 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7173 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7174 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7175 err_code |= ERR_WARN;
7176 }
7177
Willy Tarreau82ffa392013-08-13 17:19:08 +02007178 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7179 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7180 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7181 err_code |= ERR_WARN;
7182 }
7183
Pieter Baauwd551fb52013-05-08 22:49:23 +02007184#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007185 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7186 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007187 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007188 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007189 err_code |= ERR_WARN;
7190 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007191#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007192 newsrv = newsrv->next;
7193 }
7194
Willy Tarreauc1a21672009-08-16 22:37:44 +02007195 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007196 if (!curproxy->accept)
7197 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007198
Willy Tarreauc1a21672009-08-16 22:37:44 +02007199 if (curproxy->tcp_req.inspect_delay ||
7200 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007201 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007202
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007203 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007204 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007205 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007206 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007207
7208 /* both TCP and HTTP must check switching rules */
7209 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7210 }
7211
7212 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007213 if (curproxy->tcp_req.inspect_delay ||
7214 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7215 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7216
Emeric Brun97679e72010-09-23 17:56:44 +02007217 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7218 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7219
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007220 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007221 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007222 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007223 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007224
7225 /* If the backend does requires RDP cookie persistence, we have to
7226 * enable the corresponding analyser.
7227 */
7228 if (curproxy->options2 & PR_O2_RDPC_PRST)
7229 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7230 }
7231
Emeric Brunc52962f2012-11-15 18:28:02 +01007232#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007233 /* Configure SSL for each bind line.
7234 * Note: if configuration fails at some point, the ->ctx member
7235 * remains NULL so that listeners can later detach.
7236 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007237 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007238 if (!bind_conf->is_ssl) {
7239 if (bind_conf->default_ctx) {
7240 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7241 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7242 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007243 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007244 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007245 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007246 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007247 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007248 cfgerr++;
7249 continue;
7250 }
7251
Emeric Brun4b3091e2012-09-24 15:48:52 +02007252 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007253 Alert("Unable to allocate SSL session cache.\n");
7254 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007255 continue;
7256 }
7257
Emeric Brunfc0421f2012-09-07 17:30:07 +02007258 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007259 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007260 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007261#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007262
Willy Tarreaue6b98942007-10-29 01:09:36 +01007263 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007264 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007265 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007266 if (!listener->luid) {
7267 /* listener ID not set, use automatic numbering with first
7268 * spare entry starting with next_luid.
7269 */
7270 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7271 listener->conf.id.key = listener->luid = next_id;
7272 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007273 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007274 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007275
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007276 /* enable separate counters */
7277 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7278 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007279 if (!listener->name)
7280 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007281 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007282
Willy Tarreaue6b98942007-10-29 01:09:36 +01007283 if (curproxy->options & PR_O_TCP_NOLING)
7284 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007285 if (!listener->maxconn)
7286 listener->maxconn = curproxy->maxconn;
7287 if (!listener->backlog)
7288 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007289 if (!listener->maxaccept)
7290 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7291
7292 /* we want to have an optimal behaviour on single process mode to
7293 * maximize the work at once, but in multi-process we want to keep
7294 * some fairness between processes, so we target half of the max
7295 * number of events to be balanced over all the processes the proxy
7296 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7297 * used to disable the limit.
7298 */
7299 if (listener->maxaccept > 0) {
7300 if (nbproc > 1)
7301 listener->maxaccept = (listener->maxaccept + 1) / 2;
7302 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7303 }
7304
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007305 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007306 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007307 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007308 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007309
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007310 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7311 listener->options |= LI_O_TCP_RULES;
7312
Willy Tarreaude3041d2010-05-31 10:56:17 +02007313 if (curproxy->mon_mask.s_addr)
7314 listener->options |= LI_O_CHK_MONNET;
7315
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007316 /* smart accept mode is automatic in HTTP mode */
7317 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007318 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007319 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7320 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007321 }
7322
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007323 /* Release unused SSL configs */
7324 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7325 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007326 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007327#ifdef USE_OPENSSL
7328 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007329 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007330 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007331 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007332 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007333#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007334 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007335
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007336 /* Check multi-process mode compatibility for the current proxy */
7337 if (global.nbproc > 1) {
7338 int nbproc = 0;
7339 if (curproxy->bind_proc) {
7340 int proc;
7341 for (proc = 0; proc < global.nbproc; proc++) {
7342 if (curproxy->bind_proc & (1 << proc)) {
7343 nbproc++;
7344 }
7345 }
7346 } else {
7347 nbproc = global.nbproc;
7348 }
7349 if (curproxy->table.peers.name) {
7350 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7351 curproxy->id);
7352 cfgerr++;
7353 }
7354 if (nbproc > 1) {
7355 if (curproxy->uri_auth) {
7356 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7357 curproxy->id);
7358 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7359 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7360 curproxy->id);
7361 }
7362 }
7363 if (curproxy->appsession_name) {
7364 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7365 curproxy->id);
7366 }
7367 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7368 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7369 curproxy->id);
7370 }
7371 }
7372 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007373
7374 /* create the task associated with the proxy */
7375 curproxy->task = task_new();
7376 if (curproxy->task) {
7377 curproxy->task->context = curproxy;
7378 curproxy->task->process = manage_proxy;
7379 /* no need to queue, it will be done automatically if some
7380 * listener gets limited.
7381 */
7382 curproxy->task->expire = TICK_ETERNITY;
7383 } else {
7384 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7385 curproxy->id);
7386 cfgerr++;
7387 }
7388
Willy Tarreaubaaee002006-06-26 02:48:02 +02007389 curproxy = curproxy->next;
7390 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007391
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007392 /* Check multi-process mode compatibility */
7393 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007394 if (global.stats_fe && !global.stats_fe->bind_proc) {
7395 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 +01007396 }
7397 }
7398
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007399 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7400 struct auth_users *curuser;
7401 int g;
7402
7403 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7404 unsigned int group_mask = 0;
7405 char *group = NULL;
7406
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007407 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007408 continue;
7409
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007410 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007411
7412 for (g = 0; g < curuserlist->grpcnt; g++)
7413 if (!strcmp(curuserlist->groups[g], group))
7414 break;
7415
7416 if (g == curuserlist->grpcnt) {
7417 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7418 curuserlist->name, group, curuser->user);
7419 err_code |= ERR_ALERT | ERR_FATAL;
7420 goto out;
7421 }
7422
7423 group_mask |= (1 << g);
7424 }
7425
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007426 free(curuser->u.groups);
7427 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007428 }
7429
7430 for (g = 0; g < curuserlist->grpcnt; g++) {
7431 char *user = NULL;
7432
7433 if (!curuserlist->groupusers[g])
7434 continue;
7435
7436 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7437 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7438 if (!strcmp(curuser->user, user))
7439 break;
7440
7441 if (!curuser) {
7442 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7443 curuserlist->name, user, curuserlist->groups[g]);
7444 err_code |= ERR_ALERT | ERR_FATAL;
7445 goto out;
7446 }
7447
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007448 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007449 }
7450
7451 free(curuserlist->groupusers[g]);
7452 }
7453
7454 free(curuserlist->groupusers);
7455
7456#ifdef DEBUG_AUTH
7457 for (g = 0; g < curuserlist->grpcnt; g++) {
7458 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7459
7460 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007461 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007462 fprintf(stderr, " %s", curuser->user);
7463 }
7464
7465 fprintf(stderr, "\n");
7466 }
7467#endif
7468
Willy Tarreaufbb78422011-06-05 15:38:35 +02007469 }
7470
7471 /* automatically compute fullconn if not set. We must not do it in the
7472 * loop above because cross-references are not yet fully resolved.
7473 */
7474 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7475 /* If <fullconn> is not set, let's set it to 10% of the sum of
7476 * the possible incoming frontend's maxconns.
7477 */
7478 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7479 struct proxy *fe;
7480 int total = 0;
7481
7482 /* sum up the number of maxconns of frontends which
7483 * reference this backend at least once or which are
7484 * the same one ('listen').
7485 */
7486 for (fe = proxy; fe; fe = fe->next) {
7487 struct switching_rule *rule;
7488 struct hdr_exp *exp;
7489 int found = 0;
7490
7491 if (!(fe->cap & PR_CAP_FE))
7492 continue;
7493
7494 if (fe == curproxy) /* we're on a "listen" instance */
7495 found = 1;
7496
7497 if (fe->defbe.be == curproxy) /* "default_backend" */
7498 found = 1;
7499
7500 /* check if a "use_backend" rule matches */
7501 if (!found) {
7502 list_for_each_entry(rule, &fe->switching_rules, list) {
7503 if (rule->be.backend == curproxy) {
7504 found = 1;
7505 break;
7506 }
7507 }
7508 }
7509
7510 /* check if a "reqsetbe" rule matches */
7511 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7512 if (exp->action == ACT_SETBE &&
7513 (struct proxy *)exp->replace == curproxy) {
7514 found = 1;
7515 break;
7516 }
7517 }
7518
7519 /* now we've checked all possible ways to reference a backend
7520 * from a frontend.
7521 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007522 if (!found)
7523 continue;
7524 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007525 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007526 /* we have the sum of the maxconns in <total>. We only
7527 * keep 10% of that sum to set the default fullconn, with
7528 * a hard minimum of 1 (to avoid a divide by zero).
7529 */
7530 curproxy->fullconn = (total + 9) / 10;
7531 if (!curproxy->fullconn)
7532 curproxy->fullconn = 1;
7533 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007534 }
7535
Willy Tarreau056f5682010-06-06 15:51:11 +02007536 /* initialize stick-tables on backend capable proxies. This must not
7537 * be done earlier because the data size may be discovered while parsing
7538 * other proxies.
7539 */
Godbach9703e662013-12-11 21:11:41 +08007540 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7541 if (!stktable_init(&curproxy->table)) {
7542 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7543 cfgerr++;
7544 }
7545 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007546
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007547 /*
7548 * Recount currently required checks.
7549 */
7550
7551 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7552 int optnum;
7553
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007554 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7555 if (curproxy->options & cfg_opts[optnum].val)
7556 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007557
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007558 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7559 if (curproxy->options2 & cfg_opts2[optnum].val)
7560 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007561 }
7562
Willy Tarreau122541c2011-09-07 21:24:49 +02007563 if (peers) {
7564 struct peers *curpeers = peers, **last;
7565 struct peer *p, *pb;
7566
7567 /* Remove all peers sections which don't have a valid listener.
7568 * This can happen when a peers section is never referenced and
7569 * does not contain a local peer.
7570 */
7571 last = &peers;
7572 while (*last) {
7573 curpeers = *last;
7574 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007575 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007576 last = &curpeers->next;
7577 continue;
7578 }
7579
7580 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7581 curpeers->id, localpeer);
7582
7583 p = curpeers->remote;
7584 while (p) {
7585 pb = p->next;
7586 free(p->id);
7587 free(p);
7588 p = pb;
7589 }
7590
7591 /* Destroy and unlink this curpeers section.
7592 * Note: curpeers is backed up into *last.
7593 */
7594 free(curpeers->id);
7595 curpeers = curpeers->next;
7596 free(*last);
7597 *last = curpeers;
7598 }
7599 }
7600
Willy Tarreau34eb6712011-10-24 18:15:04 +02007601 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007602 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007603 MEM_F_SHARED);
7604
Willy Tarreaubb925012009-07-23 13:36:36 +02007605 if (cfgerr > 0)
7606 err_code |= ERR_ALERT | ERR_FATAL;
7607 out:
7608 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007609}
7610
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007611/*
7612 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7613 * parsing sessions.
7614 */
7615void cfg_register_keywords(struct cfg_kw_list *kwl)
7616{
7617 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7618}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007619
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007620/*
7621 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7622 */
7623void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7624{
7625 LIST_DEL(&kwl->list);
7626 LIST_INIT(&kwl->list);
7627}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007628
7629/*
7630 * Local variables:
7631 * c-indent-level: 8
7632 * c-basic-offset: 8
7633 * End:
7634 */