blob: c7a491ff8ae27ca393c48fee87b4b7eb414f40d3 [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 }
Emeric Brun850efd52014-01-29 12:24:34 +0100865 else if (!strcmp(args[0], "ssl-server-verify")) {
866 if (*(args[1]) == 0) {
867 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870 }
871 if (strcmp(args[1],"none") == 0)
872 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
873 else if (strcmp(args[1],"required") == 0)
874 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
875 else {
876 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200881 else if (!strcmp(args[0], "maxconnrate")) {
882 if (global.cps_lim != 0) {
883 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
884 err_code |= ERR_ALERT;
885 goto out;
886 }
887 if (*(args[1]) == 0) {
888 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891 }
892 global.cps_lim = atol(args[1]);
893 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200894 else if (!strcmp(args[0], "maxsessrate")) {
895 if (global.sps_lim != 0) {
896 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT;
898 goto out;
899 }
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 }
905 global.sps_lim = atol(args[1]);
906 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200907 else if (!strcmp(args[0], "maxsslrate")) {
908 if (global.ssl_lim != 0) {
909 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
910 err_code |= ERR_ALERT;
911 goto out;
912 }
913 if (*(args[1]) == 0) {
914 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
915 err_code |= ERR_ALERT | ERR_FATAL;
916 goto out;
917 }
918 global.ssl_lim = atol(args[1]);
919 }
William Lallemandd85f9172012-11-09 17:05:39 +0100920 else if (!strcmp(args[0], "maxcomprate")) {
921 if (*(args[1]) == 0) {
922 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
923 err_code |= ERR_ALERT | ERR_FATAL;
924 goto out;
925 }
926 global.comp_rate_lim = atoi(args[1]) * 1024;
927 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100928 else if (!strcmp(args[0], "maxpipes")) {
929 if (global.maxpipes != 0) {
930 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200931 err_code |= ERR_ALERT;
932 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100933 }
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100938 }
939 global.maxpipes = atol(args[1]);
940 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100941 else if (!strcmp(args[0], "maxzlibmem")) {
942 if (*(args[1]) == 0) {
943 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
944 err_code |= ERR_ALERT | ERR_FATAL;
945 goto out;
946 }
William Lallemande3a7d992012-11-20 11:25:20 +0100947 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100948 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100949 else if (!strcmp(args[0], "maxcompcpuusage")) {
950 if (*(args[1]) == 0) {
951 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
952 err_code |= ERR_ALERT | ERR_FATAL;
953 goto out;
954 }
955 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100956 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100957 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961}
962
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 else if (!strcmp(args[0], "ulimit-n")) {
964 if (global.rlimit_nofile != 0) {
965 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 if (*(args[1]) == 0) {
970 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT | ERR_FATAL;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 global.rlimit_nofile = atol(args[1]);
975 }
976 else if (!strcmp(args[0], "chroot")) {
977 if (global.chroot != NULL) {
978 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200979 err_code |= ERR_ALERT;
980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 }
982 if (*(args[1]) == 0) {
983 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 global.chroot = strdup(args[1]);
988 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200989 else if (!strcmp(args[0], "description")) {
990 int i, len=0;
991 char *d;
992
993 if (!*args[1]) {
994 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
995 file, linenum, args[0]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999
1000 for(i=1; *args[i]; i++)
1001 len += strlen(args[i])+1;
1002
1003 if (global.desc)
1004 free(global.desc);
1005
1006 global.desc = d = (char *)calloc(1, len);
1007
1008 d += sprintf(d, "%s", args[1]);
1009 for(i=2; *args[i]; i++)
1010 d += sprintf(d, " %s", args[i]);
1011 }
1012 else if (!strcmp(args[0], "node")) {
1013 int i;
1014 char c;
1015
1016 for (i=0; args[1][i]; i++) {
1017 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001018 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1019 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001020 break;
1021 }
1022
1023 if (!i || args[1][i]) {
1024 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1025 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1026 file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029 }
1030
1031 if (global.node)
1032 free(global.node);
1033
1034 global.node = strdup(args[1]);
1035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001036 else if (!strcmp(args[0], "pidfile")) {
1037 if (global.pidfile != NULL) {
1038 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001039 err_code |= ERR_ALERT;
1040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001041 }
1042 if (*(args[1]) == 0) {
1043 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 }
1047 global.pidfile = strdup(args[1]);
1048 }
Emeric Bruned760922010-10-22 17:59:25 +02001049 else if (!strcmp(args[0], "unix-bind")) {
1050 int cur_arg = 1;
1051 while (*(args[cur_arg])) {
1052 if (!strcmp(args[cur_arg], "prefix")) {
1053 if (global.unix_bind.prefix != NULL) {
1054 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1055 err_code |= ERR_ALERT;
1056 cur_arg += 2;
1057 continue;
1058 }
1059
1060 if (*(args[cur_arg+1]) == 0) {
1061 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1062 err_code |= ERR_ALERT | ERR_FATAL;
1063 goto out;
1064 }
1065 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1066 cur_arg += 2;
1067 continue;
1068 }
1069
1070 if (!strcmp(args[cur_arg], "mode")) {
1071
1072 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1073 cur_arg += 2;
1074 continue;
1075 }
1076
1077 if (!strcmp(args[cur_arg], "uid")) {
1078
1079 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1080 cur_arg += 2;
1081 continue;
1082 }
1083
1084 if (!strcmp(args[cur_arg], "gid")) {
1085
1086 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1087 cur_arg += 2;
1088 continue;
1089 }
1090
1091 if (!strcmp(args[cur_arg], "user")) {
1092 struct passwd *user;
1093
1094 user = getpwnam(args[cur_arg + 1]);
1095 if (!user) {
1096 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1097 file, linenum, args[0], args[cur_arg + 1 ]);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
1100 }
1101
1102 global.unix_bind.ux.uid = user->pw_uid;
1103 cur_arg += 2;
1104 continue;
1105 }
1106
1107 if (!strcmp(args[cur_arg], "group")) {
1108 struct group *group;
1109
1110 group = getgrnam(args[cur_arg + 1]);
1111 if (!group) {
1112 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1113 file, linenum, args[0], args[cur_arg + 1 ]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
1117
1118 global.unix_bind.ux.gid = group->gr_gid;
1119 cur_arg += 2;
1120 continue;
1121 }
1122
Willy Tarreaub48f9582011-09-05 01:17:06 +02001123 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001124 file, linenum, args[0]);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128 }
William Lallemand0f99e342011-10-12 17:50:54 +02001129 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1130 /* delete previous herited or defined syslog servers */
1131 struct logsrv *back;
1132 struct logsrv *tmp;
1133
1134 if (*(args[1]) != 0) {
1135 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1136 err_code |= ERR_ALERT | ERR_FATAL;
1137 goto out;
1138 }
1139
1140 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1141 LIST_DEL(&tmp->list);
1142 free(tmp);
1143 }
1144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001145 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001146 struct sockaddr_storage *sk;
1147 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001148 struct logsrv *logsrv;
1149
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 if (*(args[1]) == 0 || *(args[2]) == 0) {
1151 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
William Lallemand0f99e342011-10-12 17:50:54 +02001155
1156 logsrv = calloc(1, sizeof(struct logsrv));
1157
1158 logsrv->facility = get_log_facility(args[2]);
1159 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001162 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164
William Lallemand0f99e342011-10-12 17:50:54 +02001165 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001166 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001167 logsrv->level = get_log_level(args[3]);
1168 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001169 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001170 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001171 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 }
1174
William Lallemand0f99e342011-10-12 17:50:54 +02001175 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001176 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001177 logsrv->minlvl = get_log_level(args[4]);
1178 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001179 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001180 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001181 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001182 }
1183 }
1184
Willy Tarreau902636f2013-03-10 19:44:48 +01001185 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001186 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001187 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001188 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001189 free(logsrv);
1190 goto out;
1191 }
1192 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001193
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001194 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001195 if (port1 != port2) {
1196 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1197 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001198 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001199 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001200 goto out;
1201 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001202
William Lallemand0f99e342011-10-12 17:50:54 +02001203 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001204 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001205 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207
William Lallemand0f99e342011-10-12 17:50:54 +02001208 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001209 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001210 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1211 char *name;
1212 int len;
1213
1214 if (global.log_send_hostname != NULL) {
1215 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1216 err_code |= ERR_ALERT;
1217 goto out;
1218 }
1219
1220 if (*(args[1]))
1221 name = args[1];
1222 else
1223 name = hostname;
1224
1225 len = strlen(name);
1226
1227 /* We'll add a space after the name to respect the log format */
1228 free(global.log_send_hostname);
1229 global.log_send_hostname = malloc(len + 2);
1230 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1231 }
Kevinm48936af2010-12-22 16:08:21 +00001232 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1233 if (*(args[1]) == 0) {
1234 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1235 err_code |= ERR_ALERT | ERR_FATAL;
1236 goto out;
1237 }
1238 free(global.log_tag);
1239 global.log_tag = strdup(args[1]);
1240 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001241 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1242 if (global.spread_checks != 0) {
1243 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001244 err_code |= ERR_ALERT;
1245 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001246 }
1247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001251 }
1252 global.spread_checks = atol(args[1]);
1253 if (global.spread_checks < 0 || global.spread_checks > 50) {
1254 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001255 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001256 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001257 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001258 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1259#ifdef USE_CPU_AFFINITY
1260 int cur_arg, i;
1261 unsigned int proc = 0;
1262 unsigned long cpus = 0;
1263
1264 if (strcmp(args[1], "all") == 0)
1265 proc = 0xFFFFFFFF;
1266 else if (strcmp(args[1], "odd") == 0)
1267 proc = 0x55555555;
1268 else if (strcmp(args[1], "even") == 0)
1269 proc = 0xAAAAAAAA;
1270 else {
1271 proc = atoi(args[1]);
1272 if (proc >= 1 && proc <= 32)
1273 proc = 1 << (proc - 1);
1274 }
1275
1276 if (!proc || !*args[2]) {
1277 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",
1278 file, linenum, args[0]);
1279 err_code |= ERR_ALERT | ERR_FATAL;
1280 goto out;
1281 }
1282
1283 cur_arg = 2;
1284 while (*args[cur_arg]) {
1285 unsigned int low, high;
1286
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001287 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001288 char *dash = strchr(args[cur_arg], '-');
1289
1290 low = high = str2uic(args[cur_arg]);
1291 if (dash)
1292 high = str2uic(dash + 1);
1293
1294 if (high < low) {
1295 unsigned int swap = low;
1296 low = high;
1297 high = swap;
1298 }
1299
1300 if (low < 0 || high >= sizeof(long) * 8) {
1301 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1302 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306
1307 while (low <= high)
1308 cpus |= 1UL << low++;
1309 }
1310 else {
1311 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1312 file, linenum, args[0], args[cur_arg]);
1313 err_code |= ERR_ALERT | ERR_FATAL;
1314 goto out;
1315 }
1316 cur_arg++;
1317 }
1318 for (i = 0; i < 32; i++)
1319 if (proc & (1 << i))
1320 global.cpu_map[i] = cpus;
1321#else
1322 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325#endif
1326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001328 struct cfg_kw_list *kwl;
1329 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001330 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001331
1332 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1333 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1334 if (kwl->kw[index].section != CFG_GLOBAL)
1335 continue;
1336 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001337 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001338 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001339 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001340 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001341 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001342 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001343 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001344 err_code |= ERR_WARN;
1345 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001346 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001347 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001348 }
1349 }
1350 }
1351
Willy Tarreaubaaee002006-06-26 02:48:02 +02001352 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001353 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001355
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001357 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001358 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359}
1360
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001361void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001362{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001363 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001364 defproxy.mode = PR_MODE_TCP;
1365 defproxy.state = PR_STNEW;
1366 defproxy.maxconn = cfg_maxpconn;
1367 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001368
Simon Horman66183002013-02-23 10:16:43 +09001369 defproxy.defsrv.check.inter = DEF_CHKINTR;
1370 defproxy.defsrv.check.fastinter = 0;
1371 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001372 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1373 defproxy.defsrv.agent.fastinter = 0;
1374 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001375 defproxy.defsrv.check.rise = DEF_RISETIME;
1376 defproxy.defsrv.check.fall = DEF_FALLTIME;
1377 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1378 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001379 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001380 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001381 defproxy.defsrv.maxqueue = 0;
1382 defproxy.defsrv.minconn = 0;
1383 defproxy.defsrv.maxconn = 0;
1384 defproxy.defsrv.slowstart = 0;
1385 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1386 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1387 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388}
1389
Willy Tarreauade5ec42010-01-28 19:33:49 +01001390
1391static int create_cond_regex_rule(const char *file, int line,
1392 struct proxy *px, int dir, int action, int flags,
1393 const char *cmd, const char *reg, const char *repl,
1394 const char **cond_start)
1395{
1396 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001397 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001398 const char *err;
1399 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001400 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001401
1402 if (px == &defproxy) {
1403 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1404 err_code |= ERR_ALERT | ERR_FATAL;
1405 goto err;
1406 }
1407
1408 if (*reg == 0) {
1409 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto err;
1412 }
1413
1414 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1415 err_code |= ERR_WARN;
1416
Willy Tarreau5321c422010-01-28 20:35:13 +01001417 if (cond_start &&
1418 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001419 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1420 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1421 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001422 err_code |= ERR_ALERT | ERR_FATAL;
1423 goto err;
1424 }
1425 }
1426 else if (cond_start && **cond_start) {
1427 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1428 file, line, cmd, *cond_start);
1429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto err;
1431 }
1432
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001433 err_code |= warnif_cond_conflicts(cond,
1434 (dir == SMP_OPT_DIR_REQ) ?
1435 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1436 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1437 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001438
Willy Tarreauade5ec42010-01-28 19:33:49 +01001439 preg = calloc(1, sizeof(regex_t));
1440 if (!preg) {
1441 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1442 err_code = ERR_ALERT | ERR_FATAL;
1443 goto err;
1444 }
1445
1446 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1447 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1448 err_code = ERR_ALERT | ERR_FATAL;
1449 goto err;
1450 }
1451
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001452 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001453 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001454 if (repl && err) {
1455 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1456 file, line, cmd, *err);
1457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto err;
1459 }
1460
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001461 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001462 err_code |= ERR_WARN;
1463
Willy Tarreauf4068b62012-05-08 17:37:49 +02001464 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001465 return err_code;
1466 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001467 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001468 free(preg);
1469 return err_code;
1470}
1471
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001473 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001474 * Returns the error code, 0 if OK, or any combination of :
1475 * - ERR_ABORT: must abort ASAP
1476 * - ERR_FATAL: we can continue parsing but not start the service
1477 * - ERR_WARN: a warning has been emitted
1478 * - ERR_ALERT: an alert has been emitted
1479 * Only the two first ones can stop processing, the two others are just
1480 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001482int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1483{
1484 static struct peers *curpeers = NULL;
1485 struct peer *newpeer = NULL;
1486 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001487 struct bind_conf *bind_conf;
1488 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001489 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001490 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001491
1492 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001493 if (!*args[1]) {
1494 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1495 err_code |= ERR_ALERT | ERR_FATAL;
1496 goto out;
1497 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001498
1499 err = invalid_char(args[1]);
1500 if (err) {
1501 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1502 file, linenum, *err, args[0], args[1]);
1503 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001504 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001505 }
1506
1507 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1508 /*
1509 * If there are two proxies with the same name only following
1510 * combinations are allowed:
1511 */
1512 if (strcmp(curpeers->id, args[1]) == 0) {
1513 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1514 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1515 err_code |= ERR_WARN;
1516 }
1517 }
1518
1519 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1520 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1521 err_code |= ERR_ALERT | ERR_ABORT;
1522 goto out;
1523 }
1524
1525 curpeers->next = peers;
1526 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001527 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001528 curpeers->conf.line = linenum;
1529 curpeers->last_change = now.tv_sec;
1530 curpeers->id = strdup(args[1]);
1531 }
1532 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001533 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001534 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001535 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001536
1537 if (!*args[2]) {
1538 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1539 file, linenum, args[0]);
1540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
1542 }
1543
1544 err = invalid_char(args[1]);
1545 if (err) {
1546 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1547 file, linenum, *err, args[1]);
1548 err_code |= ERR_ALERT | ERR_FATAL;
1549 goto out;
1550 }
1551
1552 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1553 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1554 err_code |= ERR_ALERT | ERR_ABORT;
1555 goto out;
1556 }
1557
1558 /* the peers are linked backwards first */
1559 curpeers->count++;
1560 newpeer->next = curpeers->remote;
1561 curpeers->remote = newpeer;
1562 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001563 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001564 newpeer->conf.line = linenum;
1565
1566 newpeer->last_change = now.tv_sec;
1567 newpeer->id = strdup(args[1]);
1568
Willy Tarreau902636f2013-03-10 19:44:48 +01001569 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001570 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001571 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001572 err_code |= ERR_ALERT | ERR_FATAL;
1573 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001574 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001575
1576 proto = protocol_by_family(sk->ss_family);
1577 if (!proto || !proto->connect) {
1578 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1579 file, linenum, args[0], args[1]);
1580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001583
1584 if (port1 != port2) {
1585 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1586 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001587 err_code |= ERR_ALERT | ERR_FATAL;
1588 goto out;
1589 }
1590
Willy Tarreau2aa38802013-02-20 19:20:59 +01001591 if (!port1) {
1592 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1593 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
1596 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001597
Emeric Brun32da3c42010-09-23 18:39:19 +02001598 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001599 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001600 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001601 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001602
Emeric Brun32da3c42010-09-23 18:39:19 +02001603 if (strcmp(newpeer->id, localpeer) == 0) {
1604 /* Current is local peer, it define a frontend */
1605 newpeer->local = 1;
1606
1607 if (!curpeers->peers_fe) {
1608 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1609 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1610 err_code |= ERR_ALERT | ERR_ABORT;
1611 goto out;
1612 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001613
Willy Tarreau237250c2011-07-29 01:49:03 +02001614 init_new_proxy(curpeers->peers_fe);
1615 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001616
1617 curpeers->peers_fe->last_change = now.tv_sec;
1618 curpeers->peers_fe->id = strdup(args[1]);
1619 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001620 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001621 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1622 curpeers->peers_fe->timeout.connect = 5000;
1623 curpeers->peers_fe->accept = peer_accept;
1624 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001625 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1626 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001627
1628 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1629
Willy Tarreau902636f2013-03-10 19:44:48 +01001630 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1631 if (errmsg && *errmsg) {
1632 indent_msg(&errmsg, 2);
1633 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001634 }
1635 else
1636 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1637 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001638 err_code |= ERR_FATAL;
1639 goto out;
1640 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001641
1642 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1643 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1644 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1645 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1646 l->accept = session_accept;
1647 l->handler = process_session;
1648 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1649 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1650 global.maxsock += l->maxconn;
1651 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001652 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001653 else {
1654 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1655 file, linenum, args[0], args[1],
1656 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1657 err_code |= ERR_FATAL;
1658 goto out;
1659 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001660 }
1661 } /* neither "peer" nor "peers" */
1662 else if (*args[0] != 0) {
1663 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1664 err_code |= ERR_ALERT | ERR_FATAL;
1665 goto out;
1666 }
1667
1668out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001669 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001670 return err_code;
1671}
1672
Simon Horman69d29f92013-02-23 15:14:19 +09001673static int init_check(struct check *check, int type, const char * file, int linenum)
1674{
1675 check->type = type;
1676
1677 /* Allocate buffer for requests... */
1678 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1679 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1680 return ERR_ALERT | ERR_ABORT;
1681 }
1682 check->bi->size = global.tune.chksize;
1683
1684 /* Allocate buffer for responses... */
1685 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1686 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1687 return ERR_ALERT | ERR_ABORT;
1688 }
1689 check->bo->size = global.tune.chksize;
1690
1691 /* Allocate buffer for partial results... */
1692 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1693 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1694 return ERR_ALERT | ERR_ABORT;
1695 }
1696
1697 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1698
1699 return 0;
1700}
Emeric Brun32da3c42010-09-23 18:39:19 +02001701
Willy Tarreau3842f002009-06-14 11:39:52 +02001702int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001703{
1704 static struct proxy *curproxy = NULL;
1705 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001706 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001707 int rc;
1708 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001709 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001710 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001711 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001712 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001713 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001714
Willy Tarreau977b8e42006-12-29 14:19:17 +01001715 if (!strcmp(args[0], "listen"))
1716 rc = PR_CAP_LISTEN;
1717 else if (!strcmp(args[0], "frontend"))
1718 rc = PR_CAP_FE | PR_CAP_RS;
1719 else if (!strcmp(args[0], "backend"))
1720 rc = PR_CAP_BE | PR_CAP_RS;
1721 else if (!strcmp(args[0], "ruleset"))
1722 rc = PR_CAP_RS;
1723 else
1724 rc = PR_CAP_NONE;
1725
1726 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 if (!*args[1]) {
1728 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1729 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1730 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001731 err_code |= ERR_ALERT | ERR_ABORT;
1732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001734
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001735 err = invalid_char(args[1]);
1736 if (err) {
1737 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1738 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001739 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001740 }
1741
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001742 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1743 /*
1744 * If there are two proxies with the same name only following
1745 * combinations are allowed:
1746 *
1747 * listen backend frontend ruleset
1748 * listen - - - -
1749 * backend - - OK -
1750 * frontend - OK - -
1751 * ruleset - - - -
1752 */
1753
1754 if (!strcmp(curproxy->id, args[1]) &&
1755 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1756 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001757 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1758 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1759 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001760 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001761 }
1762 }
1763
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1765 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001766 err_code |= ERR_ALERT | ERR_ABORT;
1767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001769
Willy Tarreau97cb7802010-01-03 20:23:58 +01001770 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 curproxy->next = proxy;
1772 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001773 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1774 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001775 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001777 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778
1779 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001780 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001781 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001782
Willy Tarreau4348fad2012-09-20 16:48:07 +02001783 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1784
Willy Tarreau902636f2013-03-10 19:44:48 +01001785 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1786 if (errmsg && *errmsg) {
1787 indent_msg(&errmsg, 2);
1788 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001789 }
1790 else
1791 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1792 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001793 err_code |= ERR_FATAL;
1794 goto out;
1795 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001796
Willy Tarreau4348fad2012-09-20 16:48:07 +02001797 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001798 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001799 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001800 }
1801
1802 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001803 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001804 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001805
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001808 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001809 curproxy->no_options = defproxy.no_options;
1810 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001811 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001812 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001813 curproxy->except_net = defproxy.except_net;
1814 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001815 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001816 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001817
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001818 if (defproxy.fwdfor_hdr_len) {
1819 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1820 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1821 }
1822
Willy Tarreaub86db342009-11-30 11:50:16 +01001823 if (defproxy.orgto_hdr_len) {
1824 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1825 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1826 }
1827
Mark Lamourinec2247f02012-01-04 13:02:01 -05001828 if (defproxy.server_id_hdr_len) {
1829 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1830 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1831 }
1832
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833 if (curproxy->cap & PR_CAP_FE) {
1834 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001835 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001836 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001837
1838 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001839 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1840 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001841
1842 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1843 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844
Willy Tarreau977b8e42006-12-29 14:19:17 +01001845 if (curproxy->cap & PR_CAP_BE) {
1846 curproxy->fullconn = defproxy.fullconn;
1847 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001849 if (defproxy.check_req) {
1850 curproxy->check_req = calloc(1, defproxy.check_len);
1851 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1852 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001853 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001854
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001855 if (defproxy.expect_str) {
1856 curproxy->expect_str = strdup(defproxy.expect_str);
1857 if (defproxy.expect_regex) {
1858 /* note: this regex is known to be valid */
1859 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1860 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1861 }
1862 }
1863
Willy Tarreau67402132012-05-31 20:40:20 +02001864 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001865 if (defproxy.cookie_name)
1866 curproxy->cookie_name = strdup(defproxy.cookie_name);
1867 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001868 if (defproxy.cookie_domain)
1869 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001870
Willy Tarreau31936852010-10-06 16:59:56 +02001871 if (defproxy.cookie_maxidle)
1872 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1873
1874 if (defproxy.cookie_maxlife)
1875 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1876
Emeric Brun647caf12009-06-30 17:57:00 +02001877 if (defproxy.rdp_cookie_name)
1878 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1879 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1880
Willy Tarreau01732802007-11-01 22:48:15 +01001881 if (defproxy.url_param_name)
1882 curproxy->url_param_name = strdup(defproxy.url_param_name);
1883 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001884
Benoitaffb4812009-03-25 13:02:10 +01001885 if (defproxy.hh_name)
1886 curproxy->hh_name = strdup(defproxy.hh_name);
1887 curproxy->hh_len = defproxy.hh_len;
1888 curproxy->hh_match_domain = defproxy.hh_match_domain;
1889
Willy Tarreauef9a3602012-12-08 22:29:20 +01001890 if (defproxy.conn_src.iface_name)
1891 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1892 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001893 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001894#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001895 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001896#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001898
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001899 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001900 if (defproxy.capture_name)
1901 curproxy->capture_name = strdup(defproxy.capture_name);
1902 curproxy->capture_namelen = defproxy.capture_namelen;
1903 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905
Willy Tarreau977b8e42006-12-29 14:19:17 +01001906 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001907 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001908 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001909 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001910 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911 curproxy->uri_auth = defproxy.uri_auth;
1912 curproxy->mon_net = defproxy.mon_net;
1913 curproxy->mon_mask = defproxy.mon_mask;
1914 if (defproxy.monitor_uri)
1915 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1916 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001917 if (defproxy.defbe.name)
1918 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001919
1920 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001921 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1922 if (curproxy->conf.logformat_string &&
1923 curproxy->conf.logformat_string != default_http_log_format &&
1924 curproxy->conf.logformat_string != default_tcp_log_format &&
1925 curproxy->conf.logformat_string != clf_http_log_format)
1926 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1927
1928 if (defproxy.conf.lfs_file) {
1929 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1930 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1931 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932 }
1933
1934 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001935 curproxy->timeout.connect = defproxy.timeout.connect;
1936 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001937 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001938 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001939 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001940 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001941 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001942 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001943 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001944 }
1945
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001947
1948 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001949 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001950 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001951 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001952 LIST_INIT(&node->list);
1953 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1954 }
1955
Willy Tarreau62a61232013-04-12 18:13:46 +02001956 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1957 if (curproxy->conf.uniqueid_format_string)
1958 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1959
1960 if (defproxy.conf.uif_file) {
1961 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1962 curproxy->conf.uif_line = defproxy.conf.uif_line;
1963 }
William Lallemanda73203e2012-03-12 12:48:57 +01001964
1965 /* copy default header unique id */
1966 if (defproxy.header_unique_id)
1967 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1968
William Lallemand82fe75c2012-10-23 10:25:10 +02001969 /* default compression options */
1970 if (defproxy.comp != NULL) {
1971 curproxy->comp = calloc(1, sizeof(struct comp));
1972 curproxy->comp->algos = defproxy.comp->algos;
1973 curproxy->comp->types = defproxy.comp->types;
1974 }
1975
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001977 curproxy->conf.used_listener_id = EB_ROOT;
1978 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001979
Willy Tarreau93893792009-07-23 13:19:11 +02001980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 }
1982 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1983 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001984 /* FIXME-20070101: we should do this too at the end of the
1985 * config parsing to free all default values.
1986 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001987 free(defproxy.check_req);
1988 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001989 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001990 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001991 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001992 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001993 free(defproxy.capture_name);
1994 free(defproxy.monitor_uri);
1995 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001996 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001997 free(defproxy.fwdfor_hdr_name);
1998 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001999 free(defproxy.orgto_hdr_name);
2000 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002001 free(defproxy.server_id_hdr_name);
2002 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002003 free(defproxy.expect_str);
2004 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002005
Willy Tarreau62a61232013-04-12 18:13:46 +02002006 if (defproxy.conf.logformat_string != default_http_log_format &&
2007 defproxy.conf.logformat_string != default_tcp_log_format &&
2008 defproxy.conf.logformat_string != clf_http_log_format)
2009 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002010
Willy Tarreau62a61232013-04-12 18:13:46 +02002011 free(defproxy.conf.uniqueid_format_string);
2012 free(defproxy.conf.lfs_file);
2013 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002014
Willy Tarreaua534fea2008-08-03 12:19:50 +02002015 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002016 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002017
Willy Tarreaubaaee002006-06-26 02:48:02 +02002018 /* we cannot free uri_auth because it might already be used */
2019 init_default_instance();
2020 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002021 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2022 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002023 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002025 }
2026 else if (curproxy == NULL) {
2027 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002028 err_code |= ERR_ALERT | ERR_FATAL;
2029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002031
2032 /* update the current file and line being parsed */
2033 curproxy->conf.args.file = curproxy->conf.file;
2034 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035
2036 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002038 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002039 int cur_arg;
2040
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 if (curproxy == &defproxy) {
2042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_ALERT | ERR_FATAL;
2044 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002045 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002046 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002047 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002048
Willy Tarreau24709282013-03-10 21:32:12 +01002049 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002050 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002055
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002056 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002057
2058 /* use default settings for unix sockets */
2059 bind_conf->ux.uid = global.unix_bind.ux.uid;
2060 bind_conf->ux.gid = global.unix_bind.ux.gid;
2061 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002062
2063 /* NOTE: the following line might create several listeners if there
2064 * are comma-separated IPs or port ranges. So all further processing
2065 * will have to be applied to all listeners created after last_listen.
2066 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002067 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2068 if (errmsg && *errmsg) {
2069 indent_msg(&errmsg, 2);
2070 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002071 }
2072 else
2073 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2074 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
2077 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002078
Willy Tarreau4348fad2012-09-20 16:48:07 +02002079 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2080 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002081 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002082 }
2083
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002084 cur_arg = 2;
2085 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002086 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002087 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002088 char *err;
2089
Willy Tarreau26982662012-09-12 23:17:10 +02002090 kw = bind_find_kw(args[cur_arg]);
2091 if (kw) {
2092 char *err = NULL;
2093 int code;
2094
2095 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002096 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2097 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002098 cur_arg += 1 + kw->skip ;
2099 err_code |= ERR_ALERT | ERR_FATAL;
2100 goto out;
2101 }
2102
Willy Tarreau4348fad2012-09-20 16:48:07 +02002103 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002104 err_code |= code;
2105
2106 if (code) {
2107 if (err && *err) {
2108 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002109 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002110 }
2111 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002112 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2113 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002114 if (code & ERR_FATAL) {
2115 free(err);
2116 cur_arg += 1 + kw->skip;
2117 goto out;
2118 }
2119 }
2120 free(err);
2121 cur_arg += 1 + kw->skip;
2122 continue;
2123 }
2124
Willy Tarreau8638f482012-09-18 18:01:17 +02002125 err = NULL;
2126 if (!bind_dumped) {
2127 bind_dump_kws(&err);
2128 indent_msg(&err, 4);
2129 bind_dumped = 1;
2130 }
2131
2132 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2133 file, linenum, args[0], args[1], args[cur_arg],
2134 err ? " Registered keywords :" : "", err ? err : "");
2135 free(err);
2136
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_ALERT | ERR_FATAL;
2138 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002139 }
Willy Tarreau93893792009-07-23 13:19:11 +02002140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 }
2142 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2143 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2144 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2145 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_ALERT | ERR_FATAL;
2147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002149 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002150 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151
Willy Tarreaubaaee002006-06-26 02:48:02 +02002152 /* flush useless bits */
2153 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002155 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002156 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002158 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002159
Willy Tarreau1c47f852006-07-09 08:22:27 +02002160 if (!*args[1]) {
2161 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2162 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002163 err_code |= ERR_ALERT | ERR_FATAL;
2164 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002165 }
2166
Willy Tarreaua534fea2008-08-03 12:19:50 +02002167 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002168 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002169 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002170 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002171 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2172
Willy Tarreau93893792009-07-23 13:19:11 +02002173 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002174 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002175 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2176 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2177 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2178 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2179 else {
2180 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002183 }
2184 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002185 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002186 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002187
2188 if (curproxy == &defproxy) {
2189 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2190 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002191 err_code |= ERR_ALERT | ERR_FATAL;
2192 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002193 }
2194
2195 if (!*args[1]) {
2196 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2197 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002200 }
2201
2202 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002203 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002204
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002205 if (curproxy->uuid <= 0) {
2206 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002207 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_ALERT | ERR_FATAL;
2209 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002210 }
2211
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002212 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2213 if (node) {
2214 struct proxy *target = container_of(node, struct proxy, conf.id);
2215 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2216 file, linenum, proxy_type_str(curproxy), curproxy->id,
2217 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
2220 }
2221 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002222 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002223 else if (!strcmp(args[0], "description")) {
2224 int i, len=0;
2225 char *d;
2226
Cyril Bonté99ed3272010-01-24 23:29:44 +01002227 if (curproxy == &defproxy) {
2228 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2229 file, linenum, args[0]);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002234 if (!*args[1]) {
2235 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2236 file, linenum, args[0]);
2237 return -1;
2238 }
2239
2240 for(i=1; *args[i]; i++)
2241 len += strlen(args[i])+1;
2242
2243 d = (char *)calloc(1, len);
2244 curproxy->desc = d;
2245
2246 d += sprintf(d, "%s", args[1]);
2247 for(i=2; *args[i]; i++)
2248 d += sprintf(d, " %s", args[i]);
2249
2250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2252 curproxy->state = PR_STSTOPPED;
2253 }
2254 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2255 curproxy->state = PR_STNEW;
2256 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002257 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2258 int cur_arg = 1;
2259 unsigned int set = 0;
2260
2261 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002262 unsigned int low, high;
2263
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002264 if (strcmp(args[cur_arg], "all") == 0) {
2265 set = 0;
2266 break;
2267 }
2268 else if (strcmp(args[cur_arg], "odd") == 0) {
2269 set |= 0x55555555;
2270 }
2271 else if (strcmp(args[cur_arg], "even") == 0) {
2272 set |= 0xAAAAAAAA;
2273 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002274 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002275 char *dash = strchr(args[cur_arg], '-');
2276
2277 low = high = str2uic(args[cur_arg]);
2278 if (dash)
2279 high = str2uic(dash + 1);
2280
2281 if (high < low) {
2282 unsigned int swap = low;
2283 low = high;
2284 high = swap;
2285 }
2286
2287 if (low < 1 || high > 32) {
2288 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002289 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002292 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002293
2294 if (high > global.nbproc) {
2295 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2296 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002297 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002298 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002299 while (low <= high)
2300 set |= 1 << (low++ - 1);
2301 }
2302 else {
2303 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2304 file, linenum, args[0]);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002307 }
2308 cur_arg++;
2309 }
2310 curproxy->bind_proc = set;
2311 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002312 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002313 if (curproxy == &defproxy) {
2314 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002315 err_code |= ERR_ALERT | ERR_FATAL;
2316 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002317 }
2318
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002319 err = invalid_char(args[1]);
2320 if (err) {
2321 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2322 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002323 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002324 }
2325
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002326 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002327 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2328 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002329 err_code |= ERR_ALERT | ERR_FATAL;
2330 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002331 }
2332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2334 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335
Willy Tarreau977b8e42006-12-29 14:19:17 +01002336 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002338
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 if (*(args[1]) == 0) {
2340 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002345
Willy Tarreau67402132012-05-31 20:40:20 +02002346 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002347 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002348 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002349 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 curproxy->cookie_name = strdup(args[1]);
2351 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002352
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 cur_arg = 2;
2354 while (*(args[cur_arg])) {
2355 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002356 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 }
2358 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002359 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 }
2361 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002362 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 }
2364 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002365 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }
2367 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002368 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002370 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002371 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002374 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002376 else if (!strcmp(args[cur_arg], "httponly")) {
2377 curproxy->ck_opts |= PR_CK_HTTPONLY;
2378 }
2379 else if (!strcmp(args[cur_arg], "secure")) {
2380 curproxy->ck_opts |= PR_CK_SECURE;
2381 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002382 else if (!strcmp(args[cur_arg], "domain")) {
2383 if (!*args[cur_arg + 1]) {
2384 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2385 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002388 }
2389
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002390 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002391 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002392 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2393 " dots nor does not start with a dot."
2394 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002395 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002396 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002397 }
2398
2399 err = invalid_domainchar(args[cur_arg + 1]);
2400 if (err) {
2401 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2402 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002403 err_code |= ERR_ALERT | ERR_FATAL;
2404 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002405 }
2406
Willy Tarreau68a897b2009-12-03 23:28:34 +01002407 if (!curproxy->cookie_domain) {
2408 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2409 } else {
2410 /* one domain was already specified, add another one by
2411 * building the string which will be returned along with
2412 * the cookie.
2413 */
2414 char *new_ptr;
2415 int new_len = strlen(curproxy->cookie_domain) +
2416 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2417 new_ptr = malloc(new_len);
2418 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2419 free(curproxy->cookie_domain);
2420 curproxy->cookie_domain = new_ptr;
2421 }
Willy Tarreau31936852010-10-06 16:59:56 +02002422 cur_arg++;
2423 }
2424 else if (!strcmp(args[cur_arg], "maxidle")) {
2425 unsigned int maxidle;
2426 const char *res;
2427
2428 if (!*args[cur_arg + 1]) {
2429 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2430 file, linenum, args[cur_arg]);
2431 err_code |= ERR_ALERT | ERR_FATAL;
2432 goto out;
2433 }
2434
2435 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2436 if (res) {
2437 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2438 file, linenum, *res, args[cur_arg]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442 curproxy->cookie_maxidle = maxidle;
2443 cur_arg++;
2444 }
2445 else if (!strcmp(args[cur_arg], "maxlife")) {
2446 unsigned int maxlife;
2447 const char *res;
2448
2449 if (!*args[cur_arg + 1]) {
2450 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2451 file, linenum, args[cur_arg]);
2452 err_code |= ERR_ALERT | ERR_FATAL;
2453 goto out;
2454 }
2455
2456 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2457 if (res) {
2458 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2459 file, linenum, *res, args[cur_arg]);
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
2462 }
2463 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002464 cur_arg++;
2465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002467 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 +02002468 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002469 err_code |= ERR_ALERT | ERR_FATAL;
2470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 }
2472 cur_arg++;
2473 }
Willy Tarreau67402132012-05-31 20:40:20 +02002474 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2476 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002477 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 }
2479
Willy Tarreau67402132012-05-31 20:40:20 +02002480 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2482 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002485
Willy Tarreau67402132012-05-31 20:40:20 +02002486 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002487 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2488 file, linenum);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002492 else if (!strcmp(args[0], "persist")) { /* persist */
2493 if (*(args[1]) == 0) {
2494 Alert("parsing [%s:%d] : missing persist method.\n",
2495 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002498 }
2499
2500 if (!strncmp(args[1], "rdp-cookie", 10)) {
2501 curproxy->options2 |= PR_O2_RDPC_PRST;
2502
Emeric Brunb982a3d2010-01-04 15:45:53 +01002503 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002504 const char *beg, *end;
2505
2506 beg = args[1] + 11;
2507 end = strchr(beg, ')');
2508
2509 if (!end || end == beg) {
2510 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2511 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002514 }
2515
2516 free(curproxy->rdp_cookie_name);
2517 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2518 curproxy->rdp_cookie_len = end-beg;
2519 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002520 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002521 free(curproxy->rdp_cookie_name);
2522 curproxy->rdp_cookie_name = strdup("msts");
2523 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2524 }
2525 else { /* syntax */
2526 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002530 }
2531 }
2532 else {
2533 Alert("parsing [%s:%d] : unknown persist method.\n",
2534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002537 }
2538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002540 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002541
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002542 if (curproxy == &defproxy) {
2543 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2544 err_code |= ERR_ALERT | ERR_FATAL;
2545 goto out;
2546 }
2547
Willy Tarreau977b8e42006-12-29 14:19:17 +01002548 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002550
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002552 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 }
2557 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002558 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 curproxy->appsession_name = strdup(args[1]);
2560 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2561 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002562 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2563 if (err) {
2564 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2565 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002568 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002569 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002570
Willy Tarreau51041c72007-09-09 21:56:53 +02002571 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2572 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002573 err_code |= ERR_ALERT | ERR_ABORT;
2574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002575 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002576
2577 cur_arg = 6;
2578 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002579 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2580 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002581 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002582 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002583 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002584 } else if (!strcmp(args[cur_arg], "prefix")) {
2585 curproxy->options2 |= PR_O2_AS_PFX;
2586 } else if (!strcmp(args[cur_arg], "mode")) {
2587 if (!*args[cur_arg + 1]) {
2588 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2589 file, linenum, args[0], args[cur_arg]);
2590 err_code |= ERR_ALERT | ERR_FATAL;
2591 goto out;
2592 }
2593
2594 cur_arg++;
2595 if (!strcmp(args[cur_arg], "query-string")) {
2596 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2597 curproxy->options2 |= PR_O2_AS_M_QS;
2598 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2599 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2600 curproxy->options2 |= PR_O2_AS_M_PP;
2601 } else {
2602 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
2605 }
2606 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002607 cur_arg++;
2608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 } /* Url App Session */
2610 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002611 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002613
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002615 if (curproxy == &defproxy) {
2616 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
2619 }
2620
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621 if (*(args[4]) == 0) {
2622 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002627 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002628 curproxy->capture_name = strdup(args[2]);
2629 curproxy->capture_namelen = strlen(curproxy->capture_name);
2630 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 curproxy->to_log |= LW_COOKIE;
2632 }
2633 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2634 struct cap_hdr *hdr;
2635
2636 if (curproxy == &defproxy) {
2637 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 +02002638 err_code |= ERR_ALERT | ERR_FATAL;
2639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002640 }
2641
2642 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2643 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2644 file, linenum, args[0], args[1]);
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
2649 hdr = calloc(sizeof(struct cap_hdr), 1);
2650 hdr->next = curproxy->req_cap;
2651 hdr->name = strdup(args[3]);
2652 hdr->namelen = strlen(args[3]);
2653 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002654 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 hdr->index = curproxy->nb_req_cap++;
2656 curproxy->req_cap = hdr;
2657 curproxy->to_log |= LW_REQHDR;
2658 }
2659 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2660 struct cap_hdr *hdr;
2661
2662 if (curproxy == &defproxy) {
2663 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 +02002664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 }
2667
2668 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2669 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2670 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 }
2674 hdr = calloc(sizeof(struct cap_hdr), 1);
2675 hdr->next = curproxy->rsp_cap;
2676 hdr->name = strdup(args[3]);
2677 hdr->namelen = strlen(args[3]);
2678 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002679 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 hdr->index = curproxy->nb_rsp_cap++;
2681 curproxy->rsp_cap = hdr;
2682 curproxy->to_log |= LW_RSPHDR;
2683 }
2684 else {
2685 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002687 err_code |= ERR_ALERT | ERR_FATAL;
2688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 }
2690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002692 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002693 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002694
Willy Tarreaubaaee002006-06-26 02:48:02 +02002695 if (*(args[1]) == 0) {
2696 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2697 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
2701 curproxy->conn_retries = atol(args[1]);
2702 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002703 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002704 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002705
2706 if (curproxy == &defproxy) {
2707 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
2710 }
2711
Willy Tarreau20b0de52012-12-24 15:45:22 +01002712 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2713 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2714 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2715 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002716 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002717 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2718 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 +01002719 file, linenum, args[0]);
2720 err_code |= ERR_WARN;
2721 }
2722
Willy Tarreauff011f22011-01-06 17:51:27 +01002723 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002724
Willy Tarreauff011f22011-01-06 17:51:27 +01002725 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002726 err_code |= ERR_ALERT | ERR_ABORT;
2727 goto out;
2728 }
2729
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002730 err_code |= warnif_cond_conflicts(rule->cond,
2731 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2732 file, linenum);
2733
Willy Tarreauff011f22011-01-06 17:51:27 +01002734 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002735 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002736 else if (!strcmp(args[0], "http-response")) { /* response access control */
2737 struct http_res_rule *rule;
2738
2739 if (curproxy == &defproxy) {
2740 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
2743 }
2744
2745 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2746 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2747 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2748 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2749 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2750 file, linenum, args[0]);
2751 err_code |= ERR_WARN;
2752 }
2753
2754 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2755
2756 if (!rule) {
2757 err_code |= ERR_ALERT | ERR_ABORT;
2758 goto out;
2759 }
2760
2761 err_code |= warnif_cond_conflicts(rule->cond,
2762 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2763 file, linenum);
2764
2765 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2766 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002767 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2768 /* set the header name and length into the proxy structure */
2769 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2770 err_code |= ERR_WARN;
2771
2772 if (!*args[1]) {
2773 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2774 file, linenum, args[0]);
2775 err_code |= ERR_ALERT | ERR_FATAL;
2776 goto out;
2777 }
2778
2779 /* set the desired header name */
2780 free(curproxy->server_id_hdr_name);
2781 curproxy->server_id_hdr_name = strdup(args[1]);
2782 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2783 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002784 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002785 if (curproxy == &defproxy) {
2786 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002787 err_code |= ERR_ALERT | ERR_FATAL;
2788 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002789 }
2790
Willy Tarreauef6494c2010-01-28 17:12:36 +01002791 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002792 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2793 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002794 err_code |= ERR_ALERT | ERR_FATAL;
2795 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002796 }
2797
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002798 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2799 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2800 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002803 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002804
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002805 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002806 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002807 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002808 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002809 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002810
Cyril Bonté99ed3272010-01-24 23:29:44 +01002811 if (curproxy == &defproxy) {
2812 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002817 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002818 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2819 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002822 }
2823
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002824 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002825 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002826 err_code |= warnif_cond_conflicts(rule->cond,
2827 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2828 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002829 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002830 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002831 struct switching_rule *rule;
2832
Willy Tarreaub099aca2008-10-12 17:26:37 +02002833 if (curproxy == &defproxy) {
2834 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002837 }
2838
Willy Tarreau55ea7572007-06-17 19:56:27 +02002839 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002841
2842 if (*(args[1]) == 0) {
2843 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002844 err_code |= ERR_ALERT | ERR_FATAL;
2845 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002846 }
2847
Willy Tarreauef6494c2010-01-28 17:12:36 +01002848 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002849 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2850 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002853 }
2854
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002855 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2856 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2857 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002860 }
2861
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002862 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002863
Willy Tarreau55ea7572007-06-17 19:56:27 +02002864 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2865 rule->cond = cond;
2866 rule->be.name = strdup(args[1]);
2867 LIST_INIT(&rule->list);
2868 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2869 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002870 else if (strcmp(args[0], "use-server") == 0) {
2871 struct server_rule *rule;
2872
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_BE, file, linenum, args[0], NULL))
2880 err_code |= ERR_WARN;
2881
2882 if (*(args[1]) == 0) {
2883 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2884 err_code |= ERR_ALERT | ERR_FATAL;
2885 goto out;
2886 }
2887
2888 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2889 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2890 file, linenum, args[0]);
2891 err_code |= ERR_ALERT | ERR_FATAL;
2892 goto out;
2893 }
2894
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002895 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2896 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2897 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002898 err_code |= ERR_ALERT | ERR_FATAL;
2899 goto out;
2900 }
2901
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002902 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002903
2904 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2905 rule->cond = cond;
2906 rule->srv.name = strdup(args[1]);
2907 LIST_INIT(&rule->list);
2908 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2909 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2910 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002911 else if ((!strcmp(args[0], "force-persist")) ||
2912 (!strcmp(args[0], "ignore-persist"))) {
2913 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002914
2915 if (curproxy == &defproxy) {
2916 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
2919 }
2920
2921 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2922 err_code |= ERR_WARN;
2923
Willy Tarreauef6494c2010-01-28 17:12:36 +01002924 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002925 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2926 file, linenum, args[0]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002931 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2932 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2933 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
2936 }
2937
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002938 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2939 * where force-persist is applied.
2940 */
2941 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002942
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002943 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002944 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002945 if (!strcmp(args[0], "force-persist")) {
2946 rule->type = PERSIST_TYPE_FORCE;
2947 } else {
2948 rule->type = PERSIST_TYPE_IGNORE;
2949 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002950 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002951 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002952 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 else if (!strcmp(args[0], "stick-table")) {
2954 int myidx = 1;
2955
Emeric Brun32da3c42010-09-23 18:39:19 +02002956 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002957 curproxy->table.type = (unsigned int)-1;
2958 while (*args[myidx]) {
2959 const char *err;
2960
2961 if (strcmp(args[myidx], "size") == 0) {
2962 myidx++;
2963 if (!*(args[myidx])) {
2964 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2965 file, linenum, args[myidx-1]);
2966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
2968 }
2969 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2970 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2971 file, linenum, *err, args[myidx-1]);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002975 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002976 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002977 else if (strcmp(args[myidx], "peers") == 0) {
2978 myidx++;
Godbach50523162013-12-11 19:48:57 +08002979 if (!*(args[myidx])) {
2980 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2981 file, linenum, args[myidx-1]);
2982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
2984 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002985 curproxy->table.peers.name = strdup(args[myidx++]);
2986 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002987 else if (strcmp(args[myidx], "expire") == 0) {
2988 myidx++;
2989 if (!*(args[myidx])) {
2990 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2991 file, linenum, args[myidx-1]);
2992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2996 if (err) {
2997 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2998 file, linenum, *err, args[myidx-1]);
2999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003003 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 }
3005 else if (strcmp(args[myidx], "nopurge") == 0) {
3006 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003007 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003008 }
3009 else if (strcmp(args[myidx], "type") == 0) {
3010 myidx++;
3011 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3012 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3013 file, linenum, args[myidx]);
3014 err_code |= ERR_ALERT | ERR_FATAL;
3015 goto out;
3016 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003017 /* myidx already points to next arg */
3018 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003019 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003020 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003021 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003022
3023 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003024 nw = args[myidx];
3025 while (*nw) {
3026 /* the "store" keyword supports a comma-separated list */
3027 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003028 sa = NULL; /* store arg */
3029 while (*nw && *nw != ',') {
3030 if (*nw == '(') {
3031 *nw = 0;
3032 sa = ++nw;
3033 while (*nw != ')') {
3034 if (!*nw) {
3035 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3036 file, linenum, args[0], cw);
3037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
3039 }
3040 nw++;
3041 }
3042 *nw = '\0';
3043 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003044 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003045 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003046 if (*nw)
3047 *nw++ = '\0';
3048 type = stktable_get_data_type(cw);
3049 if (type < 0) {
3050 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3051 file, linenum, args[0], cw);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
Willy Tarreauac782882010-06-20 10:41:54 +02003055
3056 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3057 switch (err) {
3058 case PE_NONE: break;
3059 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003060 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3061 file, linenum, args[0], cw);
3062 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003063 break;
3064
3065 case PE_ARG_MISSING:
3066 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3067 file, linenum, args[0], cw);
3068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
3070
3071 case PE_ARG_NOT_USED:
3072 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3073 file, linenum, args[0], cw);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076
3077 default:
3078 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3079 file, linenum, args[0], cw);
3080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003082 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003083 }
3084 myidx++;
3085 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003086 else {
3087 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3088 file, linenum, args[myidx]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003091 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003092 }
3093
3094 if (!curproxy->table.size) {
3095 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3096 file, linenum);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 if (curproxy->table.type == (unsigned int)-1) {
3102 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3103 file, linenum);
3104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
3106 }
3107 }
3108 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003109 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003110 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003111 int myidx = 0;
3112 const char *name = NULL;
3113 int flags;
3114
3115 if (curproxy == &defproxy) {
3116 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
3121 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3122 err_code |= ERR_WARN;
3123 goto out;
3124 }
3125
3126 myidx++;
3127 if ((strcmp(args[myidx], "store") == 0) ||
3128 (strcmp(args[myidx], "store-request") == 0)) {
3129 myidx++;
3130 flags = STK_IS_STORE;
3131 }
3132 else if (strcmp(args[myidx], "store-response") == 0) {
3133 myidx++;
3134 flags = STK_IS_STORE | STK_ON_RSP;
3135 }
3136 else if (strcmp(args[myidx], "match") == 0) {
3137 myidx++;
3138 flags = STK_IS_MATCH;
3139 }
3140 else if (strcmp(args[myidx], "on") == 0) {
3141 myidx++;
3142 flags = STK_IS_MATCH | STK_IS_STORE;
3143 }
3144 else {
3145 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149
3150 if (*(args[myidx]) == 0) {
3151 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
3154 }
3155
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003156 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003157 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003158 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003159 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
3162 }
3163
3164 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003165 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3166 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3167 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003168 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003169 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003170 goto out;
3171 }
3172 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003173 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3174 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3175 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003176 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003177 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003178 goto out;
3179 }
3180 }
3181
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003182 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003183 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003184
Emeric Brunb982a3d2010-01-04 15:45:53 +01003185 if (strcmp(args[myidx], "table") == 0) {
3186 myidx++;
3187 name = args[myidx++];
3188 }
3189
Willy Tarreauef6494c2010-01-28 17:12:36 +01003190 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003191 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3192 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3193 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003194 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003195 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003196 goto out;
3197 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003198 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003199 else if (*(args[myidx])) {
3200 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3201 file, linenum, args[0], args[myidx]);
3202 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003203 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003204 goto out;
3205 }
Emeric Brun97679e72010-09-23 17:56:44 +02003206 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003207 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003208 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003209 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003210
Emeric Brunb982a3d2010-01-04 15:45:53 +01003211 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3212 rule->cond = cond;
3213 rule->expr = expr;
3214 rule->flags = flags;
3215 rule->table.name = name ? strdup(name) : NULL;
3216 LIST_INIT(&rule->list);
3217 if (flags & STK_ON_RSP)
3218 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3219 else
3220 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003223 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003224 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003225
Willy Tarreaubaaee002006-06-26 02:48:02 +02003226 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3227 curproxy->uri_auth = NULL; /* we must detach from the default config */
3228
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003229 if (!*args[1]) {
3230 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003231 } else if (!strcmp(args[1], "admin")) {
3232 struct stats_admin_rule *rule;
3233
3234 if (curproxy == &defproxy) {
3235 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3236 err_code |= ERR_ALERT | ERR_FATAL;
3237 goto out;
3238 }
3239
3240 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3241 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3242 err_code |= ERR_ALERT | ERR_ABORT;
3243 goto out;
3244 }
3245
3246 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3247 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3248 file, linenum, args[0], args[1]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003252 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3253 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3254 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
3258
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003259 err_code |= warnif_cond_conflicts(cond,
3260 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3261 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003262
3263 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3264 rule->cond = cond;
3265 LIST_INIT(&rule->list);
3266 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003267 } else if (!strcmp(args[1], "uri")) {
3268 if (*(args[2]) == 0) {
3269 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3273 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003274 err_code |= ERR_ALERT | ERR_ABORT;
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }
3277 } else if (!strcmp(args[1], "realm")) {
3278 if (*(args[2]) == 0) {
3279 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_FATAL;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3283 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_ABORT;
3285 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003286 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003287 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003288 unsigned interval;
3289
3290 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3291 if (err) {
3292 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3293 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003296 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3297 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_ALERT | ERR_ABORT;
3299 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003300 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003301 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003302 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003303
3304 if (curproxy == &defproxy) {
3305 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
3308 }
3309
3310 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3311 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3312 err_code |= ERR_ALERT | ERR_ABORT;
3313 goto out;
3314 }
3315
Willy Tarreauff011f22011-01-06 17:51:27 +01003316 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3317 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003318 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3319 file, linenum, args[0]);
3320 err_code |= ERR_WARN;
3321 }
3322
Willy Tarreauff011f22011-01-06 17:51:27 +01003323 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003324
Willy Tarreauff011f22011-01-06 17:51:27 +01003325 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
3328 }
3329
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003330 err_code |= warnif_cond_conflicts(rule->cond,
3331 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3332 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003333 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003334
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 } else if (!strcmp(args[1], "auth")) {
3336 if (*(args[2]) == 0) {
3337 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3341 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_ABORT;
3343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
3345 } else if (!strcmp(args[1], "scope")) {
3346 if (*(args[2]) == 0) {
3347 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3351 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_ABORT;
3353 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 }
3355 } else if (!strcmp(args[1], "enable")) {
3356 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3357 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_ABORT;
3359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003360 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003361 } else if (!strcmp(args[1], "hide-version")) {
3362 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3363 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003364 err_code |= ERR_ALERT | ERR_ABORT;
3365 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003366 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003367 } else if (!strcmp(args[1], "show-legends")) {
3368 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3369 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3370 err_code |= ERR_ALERT | ERR_ABORT;
3371 goto out;
3372 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003373 } else if (!strcmp(args[1], "show-node")) {
3374
3375 if (*args[2]) {
3376 int i;
3377 char c;
3378
3379 for (i=0; args[2][i]; i++) {
3380 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003381 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3382 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003383 break;
3384 }
3385
3386 if (!i || args[2][i]) {
3387 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3388 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3389 file, linenum, args[0], args[1]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
3393 }
3394
3395 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3396 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3397 err_code |= ERR_ALERT | ERR_ABORT;
3398 goto out;
3399 }
3400 } else if (!strcmp(args[1], "show-desc")) {
3401 char *desc = NULL;
3402
3403 if (*args[2]) {
3404 int i, len=0;
3405 char *d;
3406
3407 for(i=2; *args[i]; i++)
3408 len += strlen(args[i])+1;
3409
3410 desc = d = (char *)calloc(1, len);
3411
3412 d += sprintf(d, "%s", args[2]);
3413 for(i=3; *args[i]; i++)
3414 d += sprintf(d, " %s", args[i]);
3415 }
3416
3417 if (!*args[2] && !global.desc)
3418 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3419 file, linenum, args[1]);
3420 else {
3421 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3422 free(desc);
3423 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3424 err_code |= ERR_ALERT | ERR_ABORT;
3425 goto out;
3426 }
3427 free(desc);
3428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003430stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003431 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 +01003432 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003435 }
3436 }
3437 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003438 int optnum;
3439
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003440 if (*(args[1]) == '\0') {
3441 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3442 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003443 err_code |= ERR_ALERT | ERR_FATAL;
3444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003445 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003446
3447 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3448 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003449 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3450 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3451 file, linenum, cfg_opts[optnum].name);
3452 err_code |= ERR_ALERT | ERR_FATAL;
3453 goto out;
3454 }
Willy Tarreau93893792009-07-23 13:19:11 +02003455 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3456 err_code |= ERR_WARN;
3457 goto out;
3458 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003459
Willy Tarreau3842f002009-06-14 11:39:52 +02003460 curproxy->no_options &= ~cfg_opts[optnum].val;
3461 curproxy->options &= ~cfg_opts[optnum].val;
3462
3463 switch (kwm) {
3464 case KWM_STD:
3465 curproxy->options |= cfg_opts[optnum].val;
3466 break;
3467 case KWM_NO:
3468 curproxy->no_options |= cfg_opts[optnum].val;
3469 break;
3470 case KWM_DEF: /* already cleared */
3471 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003472 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003473
Willy Tarreau93893792009-07-23 13:19:11 +02003474 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003475 }
3476 }
3477
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003478 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3479 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003480 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3481 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3482 file, linenum, cfg_opts2[optnum].name);
3483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
3485 }
Willy Tarreau93893792009-07-23 13:19:11 +02003486 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3487 err_code |= ERR_WARN;
3488 goto out;
3489 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003490
Willy Tarreau3842f002009-06-14 11:39:52 +02003491 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3492 curproxy->options2 &= ~cfg_opts2[optnum].val;
3493
3494 switch (kwm) {
3495 case KWM_STD:
3496 curproxy->options2 |= cfg_opts2[optnum].val;
3497 break;
3498 case KWM_NO:
3499 curproxy->no_options2 |= cfg_opts2[optnum].val;
3500 break;
3501 case KWM_DEF: /* already cleared */
3502 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003503 }
Willy Tarreau93893792009-07-23 13:19:11 +02003504 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003505 }
3506 }
3507
Willy Tarreau3842f002009-06-14 11:39:52 +02003508 if (kwm != KWM_STD) {
3509 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003510 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003513 }
3514
Emeric Brun3a058f32009-06-30 18:26:00 +02003515 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003516 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003518 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003519 if (*(args[2]) != '\0') {
3520 if (!strcmp(args[2], "clf")) {
3521 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003522 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003523 } else {
3524 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003527 }
3528 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003529 if (curproxy->conf.logformat_string != default_http_log_format &&
3530 curproxy->conf.logformat_string != default_tcp_log_format &&
3531 curproxy->conf.logformat_string != clf_http_log_format)
3532 free(curproxy->conf.logformat_string);
3533 curproxy->conf.logformat_string = logformat;
3534
3535 free(curproxy->conf.lfs_file);
3536 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3537 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003538 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003539 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003541 if (curproxy->conf.logformat_string != default_http_log_format &&
3542 curproxy->conf.logformat_string != default_tcp_log_format &&
3543 curproxy->conf.logformat_string != clf_http_log_format)
3544 free(curproxy->conf.logformat_string);
3545 curproxy->conf.logformat_string = default_tcp_log_format;
3546
3547 free(curproxy->conf.lfs_file);
3548 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3549 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003550 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003551 else if (!strcmp(args[1], "tcpka")) {
3552 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003553 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003554 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003555
3556 if (curproxy->cap & PR_CAP_FE)
3557 curproxy->options |= PR_O_TCP_CLI_KA;
3558 if (curproxy->cap & PR_CAP_BE)
3559 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003560 }
3561 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003562 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003563 err_code |= ERR_WARN;
3564
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003566 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003567 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003568 curproxy->options2 &= ~PR_O2_CHK_ANY;
3569 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 if (!*args[2]) { /* no argument */
3571 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3572 curproxy->check_len = strlen(DEF_CHECK_REQ);
3573 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003574 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 curproxy->check_req = (char *)malloc(reqlen);
3576 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003577 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003579 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 if (*args[4])
3581 reqlen += strlen(args[4]);
3582 else
3583 reqlen += strlen("HTTP/1.0");
3584
3585 curproxy->check_req = (char *)malloc(reqlen);
3586 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003587 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003589 }
3590 else if (!strcmp(args[1], "ssl-hello-chk")) {
3591 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003592 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003594
Willy Tarreaua534fea2008-08-03 12:19:50 +02003595 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003596 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003597 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003598 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599 }
Willy Tarreau23677902007-05-08 23:50:35 +02003600 else if (!strcmp(args[1], "smtpchk")) {
3601 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003602 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003603 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003604 curproxy->options2 &= ~PR_O2_CHK_ANY;
3605 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003606
3607 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3608 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3609 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3610 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3611 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3612 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3613 curproxy->check_req = (char *)malloc(reqlen);
3614 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3615 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3616 } else {
3617 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3618 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3619 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3620 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3621 }
3622 }
3623 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003624 else if (!strcmp(args[1], "pgsql-check")) {
3625 /* use PostgreSQL request to check servers' health */
3626 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3627 err_code |= ERR_WARN;
3628
3629 free(curproxy->check_req);
3630 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003631 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003632 curproxy->options2 |= PR_O2_PGSQL_CHK;
3633
3634 if (*(args[2])) {
3635 int cur_arg = 2;
3636
3637 while (*(args[cur_arg])) {
3638 if (strcmp(args[cur_arg], "user") == 0) {
3639 char * packet;
3640 uint32_t packet_len;
3641 uint32_t pv;
3642
3643 /* suboption header - needs additional argument for it */
3644 if (*(args[cur_arg+1]) == 0) {
3645 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3646 file, linenum, args[0], args[1], args[cur_arg]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650
3651 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3652 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3653 pv = htonl(0x30000); /* protocol version 3.0 */
3654
3655 packet = (char*) calloc(1, packet_len);
3656
3657 memcpy(packet + 4, &pv, 4);
3658
3659 /* copy "user" */
3660 memcpy(packet + 8, "user", 4);
3661
3662 /* copy username */
3663 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3664
3665 free(curproxy->check_req);
3666 curproxy->check_req = packet;
3667 curproxy->check_len = packet_len;
3668
3669 packet_len = htonl(packet_len);
3670 memcpy(packet, &packet_len, 4);
3671 cur_arg += 2;
3672 } else {
3673 /* unknown suboption - catchall */
3674 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3675 file, linenum, args[0], args[1]);
3676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
3678 }
3679 } /* end while loop */
3680 }
3681 }
3682
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003683 else if (!strcmp(args[1], "redis-check")) {
3684 /* use REDIS PING request to check servers' health */
3685 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3686 err_code |= ERR_WARN;
3687
3688 free(curproxy->check_req);
3689 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003690 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003691 curproxy->options2 |= PR_O2_REDIS_CHK;
3692
3693 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3694 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3695 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3696 }
3697
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003698 else if (!strcmp(args[1], "mysql-check")) {
3699 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003700 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3701 err_code |= ERR_WARN;
3702
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003703 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003704 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003705 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003706 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003707
3708 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3709 * const char mysql40_client_auth_pkt[] = {
3710 * "\x0e\x00\x00" // packet length
3711 * "\x01" // packet number
3712 * "\x00\x00" // client capabilities
3713 * "\x00\x00\x01" // max packet
3714 * "haproxy\x00" // username (null terminated string)
3715 * "\x00" // filler (always 0x00)
3716 * "\x01\x00\x00" // packet length
3717 * "\x00" // packet number
3718 * "\x01" // COM_QUIT command
3719 * };
3720 */
3721
3722 if (*(args[2])) {
3723 int cur_arg = 2;
3724
3725 while (*(args[cur_arg])) {
3726 if (strcmp(args[cur_arg], "user") == 0) {
3727 char *mysqluser;
3728 int packetlen, reqlen, userlen;
3729
3730 /* suboption header - needs additional argument for it */
3731 if (*(args[cur_arg+1]) == 0) {
3732 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3733 file, linenum, args[0], args[1], args[cur_arg]);
3734 err_code |= ERR_ALERT | ERR_FATAL;
3735 goto out;
3736 }
3737 mysqluser = args[cur_arg + 1];
3738 userlen = strlen(mysqluser);
3739 packetlen = userlen + 7;
3740 reqlen = packetlen + 9;
3741
3742 free(curproxy->check_req);
3743 curproxy->check_req = (char *)calloc(1, reqlen);
3744 curproxy->check_len = reqlen;
3745
3746 snprintf(curproxy->check_req, 4, "%c%c%c",
3747 ((unsigned char) packetlen & 0xff),
3748 ((unsigned char) (packetlen >> 8) & 0xff),
3749 ((unsigned char) (packetlen >> 16) & 0xff));
3750
3751 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003752 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003753 curproxy->check_req[8] = 1;
3754 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3755 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3756 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3757 cur_arg += 2;
3758 } else {
3759 /* unknown suboption - catchall */
3760 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3761 file, linenum, args[0], args[1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765 } /* end while loop */
3766 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003767 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003768 else if (!strcmp(args[1], "ldap-check")) {
3769 /* use LDAP request to check servers' health */
3770 free(curproxy->check_req);
3771 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003772 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003773 curproxy->options2 |= PR_O2_LDAP_CHK;
3774
3775 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3776 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3777 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3778 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003779 else if (!strcmp(args[1], "tcp-check")) {
3780 /* use raw TCPCHK send/expect to check servers' health */
3781 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3782 err_code |= ERR_WARN;
3783
3784 free(curproxy->check_req);
3785 curproxy->check_req = NULL;
3786 curproxy->options2 &= ~PR_O2_CHK_ANY;
3787 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3788 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003789 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003790 int cur_arg;
3791
3792 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3793 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003794 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003795
Willy Tarreau87cf5142011-08-19 22:57:24 +02003796 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003797
3798 free(curproxy->fwdfor_hdr_name);
3799 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3800 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3801
3802 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3803 cur_arg = 2;
3804 while (*(args[cur_arg])) {
3805 if (!strcmp(args[cur_arg], "except")) {
3806 /* suboption except - needs additional argument for it */
3807 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3808 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3809 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003812 }
3813 /* flush useless bits */
3814 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003815 cur_arg += 2;
3816 } else if (!strcmp(args[cur_arg], "header")) {
3817 /* suboption header - needs additional argument for it */
3818 if (*(args[cur_arg+1]) == 0) {
3819 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3820 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003823 }
3824 free(curproxy->fwdfor_hdr_name);
3825 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3826 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3827 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003828 } else if (!strcmp(args[cur_arg], "if-none")) {
3829 curproxy->options &= ~PR_O_FF_ALWAYS;
3830 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003831 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003832 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003833 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003834 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003837 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003838 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003839 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003840 else if (!strcmp(args[1], "originalto")) {
3841 int cur_arg;
3842
3843 /* insert x-original-to field, but not for the IP address listed as an except.
3844 * set default options (ie: bitfield, header name, etc)
3845 */
3846
3847 curproxy->options |= PR_O_ORGTO;
3848
3849 free(curproxy->orgto_hdr_name);
3850 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3851 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3852
Willy Tarreau87cf5142011-08-19 22:57:24 +02003853 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003854 cur_arg = 2;
3855 while (*(args[cur_arg])) {
3856 if (!strcmp(args[cur_arg], "except")) {
3857 /* suboption except - needs additional argument for it */
3858 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3859 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3860 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_FATAL;
3862 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003863 }
3864 /* flush useless bits */
3865 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3866 cur_arg += 2;
3867 } else if (!strcmp(args[cur_arg], "header")) {
3868 /* suboption header - needs additional argument for it */
3869 if (*(args[cur_arg+1]) == 0) {
3870 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3871 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003874 }
3875 free(curproxy->orgto_hdr_name);
3876 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3877 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3878 cur_arg += 2;
3879 } else {
3880 /* unknown suboption - catchall */
3881 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3882 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003885 }
3886 } /* end while loop */
3887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003888 else {
3889 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003892 }
Willy Tarreau93893792009-07-23 13:19:11 +02003893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003895 else if (!strcmp(args[0], "default_backend")) {
3896 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003898
3899 if (*(args[1]) == 0) {
3900 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_ALERT | ERR_FATAL;
3902 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003903 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003904 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003905 curproxy->defbe.name = strdup(args[1]);
3906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003908 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003910
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003911 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3912 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 /* enable reconnections to dispatch */
3915 curproxy->options |= PR_O_REDISP;
3916 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003917 else if (!strcmp(args[0], "http-check")) {
3918 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003919 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003920
3921 if (strcmp(args[1], "disable-on-404") == 0) {
3922 /* enable a graceful server shutdown on an HTTP 404 response */
3923 curproxy->options |= PR_O_DISABLE404;
3924 }
Willy Tarreauef781042010-01-27 11:53:01 +01003925 else if (strcmp(args[1], "send-state") == 0) {
3926 /* enable emission of the apparent state of a server in HTTP checks */
3927 curproxy->options2 |= PR_O2_CHK_SNDST;
3928 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003929 else if (strcmp(args[1], "expect") == 0) {
3930 const char *ptr_arg;
3931 int cur_arg;
3932
3933 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3934 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938
3939 cur_arg = 2;
3940 /* consider exclamation marks, sole or at the beginning of a word */
3941 while (*(ptr_arg = args[cur_arg])) {
3942 while (*ptr_arg == '!') {
3943 curproxy->options2 ^= PR_O2_EXP_INV;
3944 ptr_arg++;
3945 }
3946 if (*ptr_arg)
3947 break;
3948 cur_arg++;
3949 }
3950 /* now ptr_arg points to the beginning of a word past any possible
3951 * exclamation mark, and cur_arg is the argument which holds this word.
3952 */
3953 if (strcmp(ptr_arg, "status") == 0) {
3954 if (!*(args[cur_arg + 1])) {
3955 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3956 file, linenum, args[0], args[1], ptr_arg);
3957 err_code |= ERR_ALERT | ERR_FATAL;
3958 goto out;
3959 }
3960 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003961 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003962 curproxy->expect_str = strdup(args[cur_arg + 1]);
3963 }
3964 else if (strcmp(ptr_arg, "string") == 0) {
3965 if (!*(args[cur_arg + 1])) {
3966 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3967 file, linenum, args[0], args[1], ptr_arg);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
3971 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003972 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003973 curproxy->expect_str = strdup(args[cur_arg + 1]);
3974 }
3975 else if (strcmp(ptr_arg, "rstatus") == 0) {
3976 if (!*(args[cur_arg + 1])) {
3977 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3978 file, linenum, args[0], args[1], ptr_arg);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
3982 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003983 free(curproxy->expect_str);
3984 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3985 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003986 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3987 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3988 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3989 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
3992 }
3993 }
3994 else if (strcmp(ptr_arg, "rstring") == 0) {
3995 if (!*(args[cur_arg + 1])) {
3996 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3997 file, linenum, args[0], args[1], ptr_arg);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
4001 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004002 free(curproxy->expect_str);
4003 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4004 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004005 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4006 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4007 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4008 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4009 err_code |= ERR_ALERT | ERR_FATAL;
4010 goto out;
4011 }
4012 }
4013 else {
4014 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4015 file, linenum, args[0], args[1], ptr_arg);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
4019 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004020 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004021 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 +02004022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004024 }
4025 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004026 else if (!strcmp(args[0], "tcp-check")) {
4027 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4028 err_code |= ERR_WARN;
4029
4030 if (strcmp(args[1], "send") == 0) {
4031 if (! *(args[2]) ) {
4032 /* SEND string expected */
4033 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4034 file, linenum, args[0], args[1], args[2]);
4035 err_code |= ERR_ALERT | ERR_FATAL;
4036 goto out;
4037 } else {
4038 struct tcpcheck_rule *tcpcheck;
4039
4040 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4041
4042 tcpcheck->action = TCPCHK_ACT_SEND;
4043 tcpcheck->string_len = strlen(args[2]);
4044 tcpcheck->string = strdup(args[2]);
4045 tcpcheck->expect_regex = NULL;
4046
4047 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4048 }
4049 }
4050 else if (strcmp(args[1], "send-binary") == 0) {
4051 if (! *(args[2]) ) {
4052 /* SEND binary string expected */
4053 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4054 file, linenum, args[0], args[1], args[2]);
4055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
4057 } else {
4058 struct tcpcheck_rule *tcpcheck;
4059 char *err = NULL;
4060
4061 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4062
4063 tcpcheck->action = TCPCHK_ACT_SEND;
4064 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4065 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4066 file, linenum, args[0], args[1], args[2], err);
4067 err_code |= ERR_ALERT | ERR_FATAL;
4068 goto out;
4069 }
4070 tcpcheck->expect_regex = NULL;
4071
4072 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4073 }
4074 }
4075 else if (strcmp(args[1], "expect") == 0) {
4076 const char *ptr_arg;
4077 int cur_arg;
4078 int inverse = 0;
4079
4080 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4081 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085
4086 cur_arg = 2;
4087 /* consider exclamation marks, sole or at the beginning of a word */
4088 while (*(ptr_arg = args[cur_arg])) {
4089 while (*ptr_arg == '!') {
4090 inverse = !inverse;
4091 ptr_arg++;
4092 }
4093 if (*ptr_arg)
4094 break;
4095 cur_arg++;
4096 }
4097 /* now ptr_arg points to the beginning of a word past any possible
4098 * exclamation mark, and cur_arg is the argument which holds this word.
4099 */
4100 if (strcmp(ptr_arg, "binary") == 0) {
4101 if (!*(args[cur_arg + 1])) {
4102 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4103 file, linenum, args[0], args[1], ptr_arg);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
4107 struct tcpcheck_rule *tcpcheck;
4108 char *err = NULL;
4109
4110 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4111
4112 tcpcheck->action = TCPCHK_ACT_EXPECT;
4113 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4114 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4115 file, linenum, args[0], args[1], args[2], err);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119 tcpcheck->expect_regex = NULL;
4120 tcpcheck->inverse = inverse;
4121
4122 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4123 }
4124 else if (strcmp(ptr_arg, "string") == 0) {
4125 if (!*(args[cur_arg + 1])) {
4126 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4127 file, linenum, args[0], args[1], ptr_arg);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 struct tcpcheck_rule *tcpcheck;
4132
4133 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4134
4135 tcpcheck->action = TCPCHK_ACT_EXPECT;
4136 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4137 tcpcheck->string = strdup(args[cur_arg + 1]);
4138 tcpcheck->expect_regex = NULL;
4139 tcpcheck->inverse = inverse;
4140
4141 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4142 }
4143 else if (strcmp(ptr_arg, "rstring") == 0) {
4144 if (!*(args[cur_arg + 1])) {
4145 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4146 file, linenum, args[0], args[1], ptr_arg);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150 struct tcpcheck_rule *tcpcheck;
4151
4152 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4153
4154 tcpcheck->action = TCPCHK_ACT_EXPECT;
4155 tcpcheck->string_len = 0;
4156 tcpcheck->string = NULL;
4157 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4158 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4159 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4160 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164 tcpcheck->inverse = inverse;
4165
4166 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4167 }
4168 else {
4169 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4170 file, linenum, args[0], args[1], ptr_arg);
4171 err_code |= ERR_ALERT | ERR_FATAL;
4172 goto out;
4173 }
4174 }
4175 else {
4176 Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
4180 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004181 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004182 if (curproxy == &defproxy) {
4183 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004186 }
4187
Willy Tarreaub80c2302007-11-30 20:51:32 +01004188 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004190
4191 if (strcmp(args[1], "fail") == 0) {
4192 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004193 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004194 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4195 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004198 }
4199
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004200 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4201 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4202 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004205 }
4206 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4207 }
4208 else {
4209 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004212 }
4213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214#ifdef TPROXY
4215 else if (!strcmp(args[0], "transparent")) {
4216 /* enable transparent proxy connections */
4217 curproxy->options |= PR_O_TRANSP;
4218 }
4219#endif
4220 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004221 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004223
Willy Tarreaubaaee002006-06-26 02:48:02 +02004224 if (*(args[1]) == 0) {
4225 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004226 err_code |= ERR_ALERT | ERR_FATAL;
4227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 }
4229 curproxy->maxconn = atol(args[1]);
4230 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004231 else if (!strcmp(args[0], "backlog")) { /* backlog */
4232 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004234
4235 if (*(args[1]) == 0) {
4236 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004239 }
4240 curproxy->backlog = atol(args[1]);
4241 }
Willy Tarreau86034312006-12-29 00:10:33 +01004242 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004245
Willy Tarreau86034312006-12-29 00:10:33 +01004246 if (*(args[1]) == 0) {
4247 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004250 }
4251 curproxy->fullconn = atol(args[1]);
4252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004253 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4254 if (*(args[1]) == 0) {
4255 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004258 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004259 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4260 if (err) {
4261 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4262 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004265 }
4266 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 }
4268 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004269 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004270 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004271 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004272
Willy Tarreaubaaee002006-06-26 02:48:02 +02004273 if (curproxy == &defproxy) {
4274 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004277 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004278 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004279 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004280
Willy Tarreau902636f2013-03-10 19:44:48 +01004281 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004282 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004283 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004284 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004285 goto out;
4286 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004287
4288 proto = protocol_by_family(sk->ss_family);
4289 if (!proto || !proto->connect) {
4290 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4291 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004292 err_code |= ERR_ALERT | ERR_FATAL;
4293 goto out;
4294 }
4295
4296 if (port1 != port2) {
4297 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4298 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004301 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004302
4303 if (!port1) {
4304 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4305 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004306 err_code |= ERR_ALERT | ERR_FATAL;
4307 goto out;
4308 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004309
Willy Tarreaud5191e72010-02-09 20:50:45 +01004310 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004311 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004312 }
4313 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004314 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004315 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004316
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004317 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4318 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004322 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004323 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004324 /**
4325 * The syntax for hash-type config element is
4326 * hash-type {map-based|consistent} [[<algo>] avalanche]
4327 *
4328 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4329 */
4330 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004331
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004332 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4333 err_code |= ERR_WARN;
4334
4335 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004336 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4337 }
4338 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004339 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4340 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004341 else if (strcmp(args[1], "avalanche") == 0) {
4342 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]);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004345 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004346 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004347 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
4350 }
Bhaskar98634f02013-10-29 23:30:51 -04004351
4352 /* set the hash function to use */
4353 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004354 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004355 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004356
4357 /* if consistent with no argument, then avalanche modifier is also applied */
4358 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4359 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004360 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004361 /* set the hash function */
4362 if (!strcmp(args[2], "sdbm")) {
4363 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4364 }
4365 else if (!strcmp(args[2], "djb2")) {
4366 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004367 } else if (!strcmp(args[2], "wt6")) {
4368 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004369 }
4370 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004371 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 -05004372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375
4376 /* set the hash modifier */
4377 if (!strcmp(args[3], "avalanche")) {
4378 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4379 }
4380 else if (*args[3]) {
4381 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4382 err_code |= ERR_ALERT | ERR_FATAL;
4383 goto out;
4384 }
Bhaskar98634f02013-10-29 23:30:51 -04004385 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004386 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004387 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004389 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004390 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004392 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004397 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399
4400 if (!*args[2]) {
4401 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4402 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_ALERT | ERR_FATAL;
4404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004406
4407 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004408 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004409 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4410 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004411 err_code |= ERR_ALERT | ERR_FATAL;
4412 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004413 }
4414
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004415 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004416 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004417 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004418 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004419
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004420 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4421 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4422 err_code |= ERR_ALERT | ERR_ABORT;
4423 goto out;
4424 }
4425
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004426 /* the servers are linked backwards first */
4427 newsrv->next = curproxy->srv;
4428 curproxy->srv = newsrv;
4429 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004430 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004431 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004433 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004434 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004435 LIST_INIT(&newsrv->pendconns);
4436 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004437 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004438 newsrv->state = SRV_RUNNING; /* early server setup */
4439 newsrv->last_change = now.tv_sec;
4440 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004441
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004442 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004443 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004444 * - IP: => port=+0, relative
4445 * - IP:N => port=N, absolute
4446 * - IP:+N => port=+N, relative
4447 * - IP:-N => port=-N, relative
4448 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004449 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004450 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004451 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004452 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004453 goto out;
4454 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004455
4456 proto = protocol_by_family(sk->ss_family);
4457 if (!proto || !proto->connect) {
4458 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4459 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004460 err_code |= ERR_ALERT | ERR_FATAL;
4461 goto out;
4462 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004463
4464 if (!port1 || !port2) {
4465 /* no port specified, +offset, -offset */
4466 newsrv->state |= SRV_MAPPORTS;
4467 }
4468 else if (port1 != port2) {
4469 /* port range */
4470 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4471 file, linenum, args[0], args[1], args[2]);
4472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
4474 }
4475 else {
4476 /* used by checks */
4477 realport = port1;
4478 }
4479
Willy Tarreaud5191e72010-02-09 20:50:45 +01004480 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004481 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4482 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004483
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004484 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004485 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4486 file, linenum, newsrv->addr.ss_family, args[2]);
4487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
4489 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004490
Simon Hormand60d6912013-11-25 10:46:36 +09004491 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004492 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004493 newsrv->check.inter = curproxy->defsrv.check.inter;
4494 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4495 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004496 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4497 newsrv->agent.port = curproxy->defsrv.agent.port;
4498 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4499 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4500 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004501 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4502 newsrv->minconn = curproxy->defsrv.minconn;
4503 newsrv->maxconn = curproxy->defsrv.maxconn;
4504 newsrv->slowstart = curproxy->defsrv.slowstart;
4505 newsrv->onerror = curproxy->defsrv.onerror;
4506 newsrv->consecutive_errors_limit
4507 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004508#ifdef OPENSSL
4509 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4510#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004511 newsrv->uweight = newsrv->iweight
4512 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513
Simon Horman69d29f92013-02-23 15:14:19 +09004514 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004515 newsrv->check.rise = curproxy->defsrv.check.rise;
4516 newsrv->check.fall = curproxy->defsrv.check.fall;
4517 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004518 newsrv->check.server = newsrv;
4519
Simon Hormand60d6912013-11-25 10:46:36 +09004520 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004521 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4522 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4523 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004524 newsrv->agent.server = newsrv;
4525
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004526 cur_arg = 3;
4527 } else {
4528 newsrv = &curproxy->defsrv;
4529 cur_arg = 1;
4530 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004531
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004533 if (!strcmp(args[cur_arg], "agent-check")) {
4534 global.maxsock++;
4535 do_agent = 1;
4536 cur_arg += 1;
4537 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4538 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4539 if (err) {
4540 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4541 file, linenum, *err, newsrv->id);
4542 err_code |= ERR_ALERT | ERR_FATAL;
4543 goto out;
4544 }
4545 if (val <= 0) {
4546 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4547 file, linenum, val, args[cur_arg], newsrv->id);
4548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
4550 }
4551 newsrv->agent.inter = val;
4552 cur_arg += 2;
4553 }
4554 else if (!strcmp(args[cur_arg], "agent-port")) {
4555 global.maxsock++;
4556 newsrv->agent.port = atol(args[cur_arg + 1]);
4557 cur_arg += 2;
4558 }
4559 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004560 newsrv->cookie = strdup(args[cur_arg + 1]);
4561 newsrv->cklen = strlen(args[cur_arg + 1]);
4562 cur_arg += 2;
4563 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004564 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004565 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4566 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4567 cur_arg += 2;
4568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004570 if (!*args[cur_arg + 1]) {
4571 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4572 file, linenum, args[cur_arg]);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576
Simon Horman58c32972013-11-25 10:46:38 +09004577 newsrv->check.rise = atol(args[cur_arg + 1]);
4578 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004579 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4580 file, linenum, args[cur_arg]);
4581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
4583 }
4584
Simon Horman125d0992013-02-24 17:23:38 +09004585 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004586 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004587 cur_arg += 2;
4588 }
4589 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004590 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004591
4592 if (!*args[cur_arg + 1]) {
4593 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4594 file, linenum, args[cur_arg]);
4595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
4597 }
4598
Simon Horman58c32972013-11-25 10:46:38 +09004599 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004600 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4601 file, linenum, args[cur_arg]);
4602 err_code |= ERR_ALERT | ERR_FATAL;
4603 goto out;
4604 }
4605
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 cur_arg += 2;
4607 }
4608 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004609 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4610 if (err) {
4611 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4612 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004615 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004616 if (val <= 0) {
4617 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4618 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004621 }
Simon Horman66183002013-02-23 10:16:43 +09004622 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004623 cur_arg += 2;
4624 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004625 else if (!strcmp(args[cur_arg], "fastinter")) {
4626 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4627 if (err) {
4628 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4629 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004630 err_code |= ERR_ALERT | ERR_FATAL;
4631 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004632 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004633 if (val <= 0) {
4634 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4635 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_ALERT | ERR_FATAL;
4637 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004638 }
Simon Horman66183002013-02-23 10:16:43 +09004639 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004640 cur_arg += 2;
4641 }
4642 else if (!strcmp(args[cur_arg], "downinter")) {
4643 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4644 if (err) {
4645 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4646 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004649 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004650 if (val <= 0) {
4651 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4652 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004655 }
Simon Horman66183002013-02-23 10:16:43 +09004656 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004657 cur_arg += 2;
4658 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004659 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004660 struct sockaddr_storage *sk;
4661 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004662 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004663
Willy Tarreau902636f2013-03-10 19:44:48 +01004664 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004665 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004666 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004667 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004668 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004669 goto out;
4670 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004671
4672 proto = protocol_by_family(sk->ss_family);
4673 if (!proto || !proto->connect) {
4674 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004675 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004676 err_code |= ERR_ALERT | ERR_FATAL;
4677 goto out;
4678 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004679
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004680 if (port1 != port2) {
4681 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4682 file, linenum, args[cur_arg], args[cur_arg + 1]);
4683 err_code |= ERR_ALERT | ERR_FATAL;
4684 goto out;
4685 }
4686
Simon Horman66183002013-02-23 10:16:43 +09004687 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004688 cur_arg += 2;
4689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004691 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 cur_arg += 2;
4693 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004694 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 newsrv->state |= SRV_BACKUP;
4696 cur_arg ++;
4697 }
Simon Hormanfa461682011-06-25 09:39:49 +09004698 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4699 newsrv->state |= SRV_NON_STICK;
4700 cur_arg ++;
4701 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004702 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4703 newsrv->state |= SRV_SEND_PROXY;
4704 cur_arg ++;
4705 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004706 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4707 newsrv->check.send_proxy = 1;
4708 cur_arg ++;
4709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004710 else if (!strcmp(args[cur_arg], "weight")) {
4711 int w;
4712 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004713 if (w < 0 || w > SRV_UWGHT_MAX) {
4714 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4715 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004716 err_code |= ERR_ALERT | ERR_FATAL;
4717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004719 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004720 cur_arg += 2;
4721 }
4722 else if (!strcmp(args[cur_arg], "minconn")) {
4723 newsrv->minconn = atol(args[cur_arg + 1]);
4724 cur_arg += 2;
4725 }
4726 else if (!strcmp(args[cur_arg], "maxconn")) {
4727 newsrv->maxconn = atol(args[cur_arg + 1]);
4728 cur_arg += 2;
4729 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004730 else if (!strcmp(args[cur_arg], "maxqueue")) {
4731 newsrv->maxqueue = atol(args[cur_arg + 1]);
4732 cur_arg += 2;
4733 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004734 else if (!strcmp(args[cur_arg], "slowstart")) {
4735 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004736 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004737 if (err) {
4738 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4739 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004740 err_code |= ERR_ALERT | ERR_FATAL;
4741 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004742 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004743 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004744 cur_arg += 2;
4745 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004746 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004747
4748 if (!*args[cur_arg + 1]) {
4749 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4750 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004751 err_code |= ERR_ALERT | ERR_FATAL;
4752 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004753 }
4754
4755 newsrv->trackit = strdup(args[cur_arg + 1]);
4756
4757 cur_arg += 2;
4758 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004759 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004760 global.maxsock++;
4761 do_check = 1;
4762 cur_arg += 1;
4763 }
Willy Tarreau96839092010-03-29 10:02:24 +02004764 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4765 newsrv->state |= SRV_MAINTAIN;
4766 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004767 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004768 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004769 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004770 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004771 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004772 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004773 if (!strcmp(args[cur_arg + 1], "none"))
4774 newsrv->observe = HANA_OBS_NONE;
4775 else if (!strcmp(args[cur_arg + 1], "layer4"))
4776 newsrv->observe = HANA_OBS_LAYER4;
4777 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4778 if (curproxy->mode != PR_MODE_HTTP) {
4779 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4780 file, linenum, args[cur_arg + 1]);
4781 err_code |= ERR_ALERT;
4782 }
4783 newsrv->observe = HANA_OBS_LAYER7;
4784 }
4785 else {
4786 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004787 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004788 file, linenum, args[cur_arg], args[cur_arg + 1]);
4789 err_code |= ERR_ALERT | ERR_FATAL;
4790 goto out;
4791 }
4792
4793 cur_arg += 2;
4794 }
4795 else if (!strcmp(args[cur_arg], "on-error")) {
4796 if (!strcmp(args[cur_arg + 1], "fastinter"))
4797 newsrv->onerror = HANA_ONERR_FASTINTER;
4798 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4799 newsrv->onerror = HANA_ONERR_FAILCHK;
4800 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4801 newsrv->onerror = HANA_ONERR_SUDDTH;
4802 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4803 newsrv->onerror = HANA_ONERR_MARKDWN;
4804 else {
4805 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004806 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004807 file, linenum, args[cur_arg], args[cur_arg + 1]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 }
4811
4812 cur_arg += 2;
4813 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004814 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4815 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4816 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4817 else {
4818 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4819 file, linenum, args[cur_arg], args[cur_arg + 1]);
4820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
4822 }
4823
4824 cur_arg += 2;
4825 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004826 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4827 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4828 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4829 else {
4830 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4831 file, linenum, args[cur_arg], args[cur_arg + 1]);
4832 err_code |= ERR_ALERT | ERR_FATAL;
4833 goto out;
4834 }
4835
4836 cur_arg += 2;
4837 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004838 else if (!strcmp(args[cur_arg], "error-limit")) {
4839 if (!*args[cur_arg + 1]) {
4840 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4841 file, linenum, args[cur_arg]);
4842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
4844 }
4845
4846 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4847
4848 if (newsrv->consecutive_errors_limit <= 0) {
4849 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4850 file, linenum, args[cur_arg]);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004854 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004855 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004856 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004857 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004858 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004859 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004860
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004862 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4863 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004864 err_code |= ERR_ALERT | ERR_FATAL;
4865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004867
Willy Tarreauef9a3602012-12-08 22:29:20 +01004868 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004869 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004870 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004871 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004872 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004873 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004874 goto out;
4875 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004876
4877 proto = protocol_by_family(sk->ss_family);
4878 if (!proto || !proto->connect) {
4879 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4880 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
4883 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004884
Willy Tarreauef9a3602012-12-08 22:29:20 +01004885 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004886
4887 if (port_low != port_high) {
4888 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004889
4890 if (!port_low || !port_high) {
4891 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4892 file, linenum, args[cur_arg], args[cur_arg + 1]);
4893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
4895 }
4896
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004897 if (port_low <= 0 || port_low > 65535 ||
4898 port_high <= 0 || port_high > 65535 ||
4899 port_low > port_high) {
4900 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4901 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004904 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004905 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4906 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4907 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004908 }
4909
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004911 while (*(args[cur_arg])) {
4912 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004913#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4914#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004915 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004916 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4917 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004920 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004921#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004922 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004923 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004924 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004925 err_code |= ERR_ALERT | ERR_FATAL;
4926 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004927 }
4928 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004929 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4930 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004931 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004932 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4933 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004934 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4935 char *name, *end;
4936
4937 name = args[cur_arg+1] + 7;
4938 while (isspace(*name))
4939 name++;
4940
4941 end = name;
4942 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4943 end++;
4944
Willy Tarreauef9a3602012-12-08 22:29:20 +01004945 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4946 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4947 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4948 newsrv->conn_src.bind_hdr_len = end - name;
4949 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4950 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4951 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004952
4953 /* now look for an occurrence number */
4954 while (isspace(*end))
4955 end++;
4956 if (*end == ',') {
4957 end++;
4958 name = end;
4959 if (*end == '-')
4960 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004961 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004962 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004963 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004964 }
4965
Willy Tarreauef9a3602012-12-08 22:29:20 +01004966 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004967 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4968 " occurrences values smaller than %d.\n",
4969 file, linenum, MAX_HDR_HISTORY);
4970 err_code |= ERR_ALERT | ERR_FATAL;
4971 goto out;
4972 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004973 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004974 struct sockaddr_storage *sk;
4975 int port1, port2;
4976
Willy Tarreau902636f2013-03-10 19:44:48 +01004977 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004978 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004979 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004980 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004981 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004982 goto out;
4983 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004984
4985 proto = protocol_by_family(sk->ss_family);
4986 if (!proto || !proto->connect) {
4987 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4988 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
4991 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004992
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004993 if (port1 != port2) {
4994 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4995 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
4998 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004999 newsrv->conn_src.tproxy_addr = *sk;
5000 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005001 }
5002 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005003#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005004 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005005#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005006 cur_arg += 2;
5007 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005008#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005009 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005010 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005013#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005014 } /* "usesrc" */
5015
5016 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5017#ifdef SO_BINDTODEVICE
5018 if (!*args[cur_arg + 1]) {
5019 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5020 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005023 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005024 free(newsrv->conn_src.iface_name);
5025 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5026 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005027 global.last_checks |= LSTCHK_NETADM;
5028#else
5029 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5030 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005033#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005034 cur_arg += 2;
5035 continue;
5036 }
5037 /* this keyword in not an option of "source" */
5038 break;
5039 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005041 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005042 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5043 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005046 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005048 static int srv_dumped;
5049 struct srv_kw *kw;
5050 char *err;
5051
5052 kw = srv_find_kw(args[cur_arg]);
5053 if (kw) {
5054 char *err = NULL;
5055 int code;
5056
5057 if (!kw->parse) {
5058 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5059 file, linenum, args[0], args[1], args[cur_arg]);
5060 cur_arg += 1 + kw->skip ;
5061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
5063 }
5064
5065 if (defsrv && !kw->default_ok) {
5066 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5067 file, linenum, args[0], args[1], args[cur_arg]);
5068 cur_arg += 1 + kw->skip ;
5069 err_code |= ERR_ALERT;
5070 continue;
5071 }
5072
5073 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5074 err_code |= code;
5075
5076 if (code) {
5077 if (err && *err) {
5078 indent_msg(&err, 2);
5079 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5080 }
5081 else
5082 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5083 file, linenum, args[0], args[1], args[cur_arg]);
5084 if (code & ERR_FATAL) {
5085 free(err);
5086 cur_arg += 1 + kw->skip;
5087 goto out;
5088 }
5089 }
5090 free(err);
5091 cur_arg += 1 + kw->skip;
5092 continue;
5093 }
5094
5095 err = NULL;
5096 if (!srv_dumped) {
5097 srv_dump_kws(&err);
5098 indent_msg(&err, 4);
5099 srv_dumped = 1;
5100 }
5101
5102 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5103 file, linenum, args[0], args[1], args[cur_arg],
5104 err ? " Registered keywords :" : "", err ? err : "");
5105 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005106
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 }
5110 }
5111
Simon Horman8c3d0be2013-11-25 10:46:40 +09005112 /* Set initial drain state using now-configured weight */
5113 set_server_drain_state(newsrv);
5114
Willy Tarreaubaaee002006-06-26 02:48:02 +02005115 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005116 int ret;
5117
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005118 if (newsrv->trackit) {
5119 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5120 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005123 }
5124
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005125 /* If neither a port nor an addr was specified and no check transport
5126 * layer is forced, then the transport layer used by the checks is the
5127 * same as for the production traffic. Otherwise we use raw_sock by
5128 * default, unless one is specified.
5129 */
Simon Horman66183002013-02-23 10:16:43 +09005130 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005131#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005132 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02005133#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005134 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5135 }
Simon Horman66183002013-02-23 10:16:43 +09005136 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005137 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005138 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005139
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005140 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005141 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005142
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005143 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005144 /* not yet valid, because no port was set on
5145 * the server either. We'll check if we have
5146 * a known port on the first listener.
5147 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005148 struct listener *l;
5149
5150 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005151 newsrv->check.port = get_host_port(&l->addr);
5152 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005153 break;
5154 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005155 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005156 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005157 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5158 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02005159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005162
Willy Tarreau2f075e92013-12-03 11:11:34 +01005163 /* note: check type will be set during the config review phase */
5164 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005165 if (ret) {
5166 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005167 goto out;
5168 }
5169
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005170 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
5172
Simon Hormand60d6912013-11-25 10:46:36 +09005173 if (do_agent) {
5174 int ret;
5175
5176 if (!newsrv->agent.port) {
5177 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5178 file, linenum, newsrv->id);
5179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
5182
5183 if (!newsrv->agent.inter)
5184 newsrv->agent.inter = newsrv->check.inter;
5185
5186 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5187 if (ret) {
5188 err_code |= ret;
5189 goto out;
5190 }
5191
Willy Tarreau33434322013-12-11 21:15:19 +01005192 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005193 }
5194
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005195 if (!defsrv) {
5196 if (newsrv->state & SRV_BACKUP)
5197 curproxy->srv_bck++;
5198 else
5199 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005200
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005201 newsrv->prev_state = newsrv->state;
5202 }
William Lallemanda73203e2012-03-12 12:48:57 +01005203 }
5204
5205 else if (strcmp(args[0], "unique-id-format") == 0) {
5206 if (!*(args[1])) {
5207 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
5210 }
William Lallemand3203ff42012-11-11 17:30:56 +01005211 if (*(args[2])) {
5212 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
5215 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005216 free(curproxy->conf.uniqueid_format_string);
5217 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005218
Willy Tarreau62a61232013-04-12 18:13:46 +02005219 free(curproxy->conf.uif_file);
5220 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5221 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005222 }
William Lallemanda73203e2012-03-12 12:48:57 +01005223
5224 else if (strcmp(args[0], "unique-id-header") == 0) {
5225 if (!*(args[1])) {
5226 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229 }
5230 free(curproxy->header_unique_id);
5231 curproxy->header_unique_id = strdup(args[1]);
5232 }
5233
William Lallemand723b73a2012-02-08 16:37:49 +01005234 else if (strcmp(args[0], "log-format") == 0) {
5235 if (!*(args[1])) {
5236 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5237 err_code |= ERR_ALERT | ERR_FATAL;
5238 goto out;
5239 }
William Lallemand3203ff42012-11-11 17:30:56 +01005240 if (*(args[2])) {
5241 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
5244 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005245
Willy Tarreau62a61232013-04-12 18:13:46 +02005246 if (curproxy->conf.logformat_string != default_http_log_format &&
5247 curproxy->conf.logformat_string != default_tcp_log_format &&
5248 curproxy->conf.logformat_string != clf_http_log_format)
5249 free(curproxy->conf.logformat_string);
5250 curproxy->conf.logformat_string = strdup(args[1]);
5251
5252 free(curproxy->conf.lfs_file);
5253 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5254 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005255
5256 /* get a chance to improve log-format error reporting by
5257 * reporting the correct line-number when possible.
5258 */
5259 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5260 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5261 file, linenum, curproxy->id);
5262 err_code |= ERR_WARN;
5263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 }
William Lallemand723b73a2012-02-08 16:37:49 +01005265
William Lallemand0f99e342011-10-12 17:50:54 +02005266 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5267 /* delete previous herited or defined syslog servers */
5268 struct logsrv *back;
5269
5270 if (*(args[1]) != 0) {
5271 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
5274 }
5275
William Lallemand723b73a2012-02-08 16:37:49 +01005276 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5277 LIST_DEL(&tmplogsrv->list);
5278 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005279 }
5280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005282 struct logsrv *logsrv;
5283
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005285 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005286 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005287 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005288 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005289 LIST_INIT(&node->list);
5290 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
5293 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005294 struct sockaddr_storage *sk;
5295 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005296
5297 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298
William Lallemand0f99e342011-10-12 17:50:54 +02005299 logsrv->facility = get_log_facility(args[2]);
5300 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005301 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304
Willy Tarreaubaaee002006-06-26 02:48:02 +02005305 }
5306
William Lallemand0f99e342011-10-12 17:50:54 +02005307 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005308 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005309 logsrv->level = get_log_level(args[3]);
5310 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005311 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 }
5316 }
5317
William Lallemand0f99e342011-10-12 17:50:54 +02005318 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005319 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005320 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005321 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005322 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005326 }
5327 }
5328
Willy Tarreau902636f2013-03-10 19:44:48 +01005329 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005330 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005331 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005332 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005333 goto out;
5334 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005335
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005336 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005337
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005338 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005339 if (port1 != port2) {
5340 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5341 file, linenum, args[0], args[1]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005346 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005347 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
William Lallemand0f99e342011-10-12 17:50:54 +02005349
5350 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005351 }
5352 else {
5353 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5354 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 }
5358 }
5359 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005360 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005361 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005362 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005363 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005364
Willy Tarreau977b8e42006-12-29 14:19:17 +01005365 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005366 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005367
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005369 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5370 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005371 err_code |= ERR_ALERT | ERR_FATAL;
5372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005374
5375 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005376 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5377 free(curproxy->conn_src.iface_name);
5378 curproxy->conn_src.iface_name = NULL;
5379 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005380
Willy Tarreau902636f2013-03-10 19:44:48 +01005381 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005382 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005383 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005384 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005385 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005386 goto out;
5387 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005388
5389 proto = protocol_by_family(sk->ss_family);
5390 if (!proto || !proto->connect) {
5391 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005392 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005393 err_code |= ERR_ALERT | ERR_FATAL;
5394 goto out;
5395 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005396
5397 if (port1 != port2) {
5398 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5399 file, linenum, args[0], args[1]);
5400 err_code |= ERR_ALERT | ERR_FATAL;
5401 goto out;
5402 }
5403
Willy Tarreauef9a3602012-12-08 22:29:20 +01005404 curproxy->conn_src.source_addr = *sk;
5405 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005406
5407 cur_arg = 2;
5408 while (*(args[cur_arg])) {
5409 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005410#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5411#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005412 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005413 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5414 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005415 err_code |= ERR_ALERT | ERR_FATAL;
5416 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005417 }
5418#endif
5419 if (!*args[cur_arg + 1]) {
5420 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5421 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005424 }
5425
5426 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005427 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5428 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005429 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005430 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5431 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005432 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5433 char *name, *end;
5434
5435 name = args[cur_arg+1] + 7;
5436 while (isspace(*name))
5437 name++;
5438
5439 end = name;
5440 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5441 end++;
5442
Willy Tarreauef9a3602012-12-08 22:29:20 +01005443 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5444 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5445 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5446 curproxy->conn_src.bind_hdr_len = end - name;
5447 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5448 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5449 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005450
5451 /* now look for an occurrence number */
5452 while (isspace(*end))
5453 end++;
5454 if (*end == ',') {
5455 end++;
5456 name = end;
5457 if (*end == '-')
5458 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005459 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005460 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005461 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005462 }
5463
Willy Tarreauef9a3602012-12-08 22:29:20 +01005464 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005465 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5466 " occurrences values smaller than %d.\n",
5467 file, linenum, MAX_HDR_HISTORY);
5468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
5470 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005471 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005472 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005473
Willy Tarreau902636f2013-03-10 19:44:48 +01005474 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005475 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005476 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005477 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005478 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005479 goto out;
5480 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005481
5482 proto = protocol_by_family(sk->ss_family);
5483 if (!proto || !proto->connect) {
5484 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5485 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005489
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005490 if (port1 != port2) {
5491 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5492 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005493 err_code |= ERR_ALERT | ERR_FATAL;
5494 goto out;
5495 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005496 curproxy->conn_src.tproxy_addr = *sk;
5497 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005498 }
5499 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005500#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005501 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005502#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005503#else /* no TPROXY support */
5504 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005505 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005506 err_code |= ERR_ALERT | ERR_FATAL;
5507 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005508#endif
5509 cur_arg += 2;
5510 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005511 }
5512
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005513 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5514#ifdef SO_BINDTODEVICE
5515 if (!*args[cur_arg + 1]) {
5516 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5517 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005520 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005521 free(curproxy->conn_src.iface_name);
5522 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5523 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005524 global.last_checks |= LSTCHK_NETADM;
5525#else
5526 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5527 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005530#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005531 cur_arg += 2;
5532 continue;
5533 }
5534 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005535 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005538 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005539 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005540 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5541 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5542 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005545 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005546 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005547 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005550 err_code |= ERR_ALERT | ERR_FATAL;
5551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005552 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005553
5554 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005555 SMP_OPT_DIR_REQ, ACT_REPLACE, 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 Tarreaubaaee002006-06-26 02:48:02 +02005559 }
5560 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
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_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005563 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005564 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 }
5567 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005568 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005569 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005570 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005571 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005572 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005573 }
5574 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005575 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005576 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005577 args[0], args[1], NULL, (const char **)args+2);
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], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 0,
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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005588 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
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_TARPIT, 0,
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 Tarreaub8750a82006-09-03 09:56:00 +02005594 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005595 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005598 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005599 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005600 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005601 }
5602 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a 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_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005605 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005606 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005607 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005609 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005610 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5612 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005616
5617 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005618 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005619 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005620 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 }
5623 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005624 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005625 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005626 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005627 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 }
5630 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005631 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005632 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005633 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005634 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005636 }
5637 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005638 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005639 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005640 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005641 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005643 }
5644 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005645 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005646 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005647 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005648 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005651 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005652 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005653 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005654 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005655 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005656 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005659 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005660
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 if (curproxy == &defproxy) {
5662 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005665 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005666 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005667 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 if (*(args[1]) == 0) {
5670 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005674
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005675 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005676 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5677 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5678 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
5681 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005682 err_code |= warnif_cond_conflicts(cond,
5683 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5684 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005685 }
5686 else if (*args[2]) {
5687 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5688 file, linenum, args[0], args[2]);
5689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
5691 }
5692
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005693 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005694 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005695 wl->s = strdup(args[1]);
5696 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005697 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 }
5699 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005700 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005701 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5702 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005706
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_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005709 args[0], args[1], args[2], (const char **)args+3);
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], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005714 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005715 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005716 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005717 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005719 }
5720 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005721 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005722 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005723 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005724 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005725 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 }
5727 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005728 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5730 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 }
5734
Willy Tarreauade5ec42010-01-28 19:33:49 +01005735 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005736 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005737 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005738 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 }
5741 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005742 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005743 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005744 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005745 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005747 }
5748 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005749 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005750 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005751 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005752 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 }
5755 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005756 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005757
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 if (curproxy == &defproxy) {
5759 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005762 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005763 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005764 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 if (*(args[1]) == 0) {
5767 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 }
5771
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005772 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005773 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5774 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5775 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
5778 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005779 err_code |= warnif_cond_conflicts(cond,
5780 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5781 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005782 }
5783 else if (*args[2]) {
5784 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5785 file, linenum, args[0], args[2]);
5786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
5789
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005790 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005791 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005792 wl->s = strdup(args[1]);
5793 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 }
5795 else if (!strcmp(args[0], "errorloc") ||
5796 !strcmp(args[0], "errorloc302") ||
5797 !strcmp(args[0], "errorloc303")) { /* error location */
5798 int errnum, errlen;
5799 char *err;
5800
Willy Tarreau977b8e42006-12-29 14:19:17 +01005801 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005802 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005803
Willy Tarreaubaaee002006-06-26 02:48:02 +02005804 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005805 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005806 err_code |= ERR_ALERT | ERR_FATAL;
5807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
5809
5810 errnum = atol(args[1]);
5811 if (!strcmp(args[0], "errorloc303")) {
5812 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5813 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5814 } else {
5815 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5816 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5817 }
5818
Willy Tarreau0f772532006-12-23 20:51:41 +01005819 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5820 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005821 chunk_destroy(&curproxy->errmsg[rc]);
5822 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005823 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005826
5827 if (rc >= HTTP_ERR_SIZE) {
5828 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5829 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005830 free(err);
5831 }
5832 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005833 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5834 int errnum, errlen, fd;
5835 char *err;
5836 struct stat stat;
5837
5838 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005839 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005840
5841 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005842 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005845 }
5846
5847 fd = open(args[2], O_RDONLY);
5848 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5849 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5850 file, linenum, args[2], args[1]);
5851 if (fd >= 0)
5852 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005853 err_code |= ERR_ALERT | ERR_FATAL;
5854 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005855 }
5856
Willy Tarreau27a674e2009-08-17 07:23:33 +02005857 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005858 errlen = stat.st_size;
5859 } else {
5860 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005861 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005862 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005863 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005864 }
5865
5866 err = malloc(errlen); /* malloc() must succeed during parsing */
5867 errnum = read(fd, err, errlen);
5868 if (errnum != errlen) {
5869 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5870 file, linenum, args[2], args[1]);
5871 close(fd);
5872 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005875 }
5876 close(fd);
5877
5878 errnum = atol(args[1]);
5879 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5880 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005881 chunk_destroy(&curproxy->errmsg[rc]);
5882 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005883 break;
5884 }
5885 }
5886
5887 if (rc >= HTTP_ERR_SIZE) {
5888 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5889 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005890 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005891 free(err);
5892 }
5893 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005894 else if (!strcmp(args[0], "compression")) {
5895 struct comp *comp;
5896 if (curproxy->comp == NULL) {
5897 comp = calloc(1, sizeof(struct comp));
5898 curproxy->comp = comp;
5899 } else {
5900 comp = curproxy->comp;
5901 }
5902
5903 if (!strcmp(args[1], "algo")) {
5904 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005905 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005906
William Lallemand82fe75c2012-10-23 10:25:10 +02005907 cur_arg = 2;
5908 if (!*args[cur_arg]) {
5909 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5910 file, linenum, args[0]);
5911 err_code |= ERR_ALERT | ERR_FATAL;
5912 goto out;
5913 }
5914 while (*(args[cur_arg])) {
5915 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5916 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5917 file, linenum, args[0], args[cur_arg]);
5918 err_code |= ERR_ALERT | ERR_FATAL;
5919 goto out;
5920 }
William Lallemand552df672012-11-07 13:21:47 +01005921 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5922 curproxy->comp->algos->end(&ctx);
5923 } else {
5924 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5925 file, linenum, args[0], args[cur_arg]);
5926 err_code |= ERR_ALERT | ERR_FATAL;
5927 goto out;
5928 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005929 cur_arg ++;
5930 continue;
5931 }
5932 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005933 else if (!strcmp(args[1], "offload")) {
5934 comp->offload = 1;
5935 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005936 else if (!strcmp(args[1], "type")) {
5937 int cur_arg;
5938 cur_arg = 2;
5939 if (!*args[cur_arg]) {
5940 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5941 file, linenum, args[0]);
5942 err_code |= ERR_ALERT | ERR_FATAL;
5943 goto out;
5944 }
5945 while (*(args[cur_arg])) {
5946 comp_append_type(comp, args[cur_arg]);
5947 cur_arg ++;
5948 continue;
5949 }
5950 }
5951 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005952 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005953 file, linenum, args[0]);
5954 err_code |= ERR_ALERT | ERR_FATAL;
5955 goto out;
5956 }
5957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005959 struct cfg_kw_list *kwl;
5960 int index;
5961
5962 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5963 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5964 if (kwl->kw[index].section != CFG_LISTEN)
5965 continue;
5966 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5967 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005968 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005969 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005970 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005973 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005974 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005975 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005976 err_code |= ERR_WARN;
5977 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005978 }
Willy Tarreau93893792009-07-23 13:19:11 +02005979 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005980 }
5981 }
5982 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005983
Willy Tarreau6daf3432008-01-22 16:44:08 +01005984 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005985 err_code |= ERR_ALERT | ERR_FATAL;
5986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005987 }
Willy Tarreau93893792009-07-23 13:19:11 +02005988 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005989 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005990 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991}
5992
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005993int
5994cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5995{
5996
5997 int err_code = 0;
5998 const char *err;
5999
6000 if (!strcmp(args[0], "userlist")) { /* new userlist */
6001 struct userlist *newul;
6002
6003 if (!*args[1]) {
6004 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6005 file, linenum, args[0]);
6006 err_code |= ERR_ALERT | ERR_FATAL;
6007 goto out;
6008 }
6009
6010 err = invalid_char(args[1]);
6011 if (err) {
6012 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6013 file, linenum, *err, args[0], args[1]);
6014 err_code |= ERR_ALERT | ERR_FATAL;
6015 goto out;
6016 }
6017
6018 for (newul = userlist; newul; newul = newul->next)
6019 if (!strcmp(newul->name, args[1])) {
6020 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6021 file, linenum, args[1]);
6022 err_code |= ERR_WARN;
6023 goto out;
6024 }
6025
6026 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6027 if (!newul) {
6028 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6029 err_code |= ERR_ALERT | ERR_ABORT;
6030 goto out;
6031 }
6032
6033 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6034 newul->name = strdup(args[1]);
6035
6036 if (!newul->groupusers | !newul->name) {
6037 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6038 err_code |= ERR_ALERT | ERR_ABORT;
6039 goto out;
6040 }
6041
6042 newul->next = userlist;
6043 userlist = newul;
6044
6045 } else if (!strcmp(args[0], "group")) { /* new group */
6046 int cur_arg, i;
6047 const char *err;
6048
6049 if (!*args[1]) {
6050 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6051 file, linenum, args[0]);
6052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
6054 }
6055
6056 err = invalid_char(args[1]);
6057 if (err) {
6058 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6059 file, linenum, *err, args[0], args[1]);
6060 err_code |= ERR_ALERT | ERR_FATAL;
6061 goto out;
6062 }
6063
6064 for(i = 0; i < userlist->grpcnt; i++)
6065 if (!strcmp(userlist->groups[i], args[1])) {
6066 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6067 file, linenum, args[1], userlist->name);
6068 err_code |= ERR_ALERT;
6069 goto out;
6070 }
6071
6072 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6073 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6074 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6075 err_code |= ERR_ALERT | ERR_FATAL;
6076 goto out;
6077 }
6078
6079 cur_arg = 2;
6080
6081 while (*args[cur_arg]) {
6082 if (!strcmp(args[cur_arg], "users")) {
6083 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6084 cur_arg += 2;
6085 continue;
6086 } else {
6087 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6088 file, linenum, args[0]);
6089 err_code |= ERR_ALERT | ERR_FATAL;
6090 goto out;
6091 }
6092 }
6093
6094 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6095 } else if (!strcmp(args[0], "user")) { /* new user */
6096 struct auth_users *newuser;
6097 int cur_arg;
6098
6099 if (!*args[1]) {
6100 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6101 file, linenum, args[0]);
6102 err_code |= ERR_ALERT | ERR_FATAL;
6103 goto out;
6104 }
6105
6106 for (newuser = userlist->users; newuser; newuser = newuser->next)
6107 if (!strcmp(newuser->user, args[1])) {
6108 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6109 file, linenum, args[1], userlist->name);
6110 err_code |= ERR_ALERT;
6111 goto out;
6112 }
6113
6114 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6115 if (!newuser) {
6116 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6117 err_code |= ERR_ALERT | ERR_ABORT;
6118 goto out;
6119 }
6120
6121 newuser->user = strdup(args[1]);
6122
6123 newuser->next = userlist->users;
6124 userlist->users = newuser;
6125
6126 cur_arg = 2;
6127
6128 while (*args[cur_arg]) {
6129 if (!strcmp(args[cur_arg], "password")) {
6130#ifndef CONFIG_HAP_CRYPT
6131 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6132 file, linenum);
6133 err_code |= ERR_ALERT;
6134#endif
6135 newuser->pass = strdup(args[cur_arg + 1]);
6136 cur_arg += 2;
6137 continue;
6138 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6139 newuser->pass = strdup(args[cur_arg + 1]);
6140 newuser->flags |= AU_O_INSECURE;
6141 cur_arg += 2;
6142 continue;
6143 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006144 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006145 cur_arg += 2;
6146 continue;
6147 } else {
6148 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6149 file, linenum, args[0]);
6150 err_code |= ERR_ALERT | ERR_FATAL;
6151 goto out;
6152 }
6153 }
6154 } else {
6155 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6156 err_code |= ERR_ALERT | ERR_FATAL;
6157 }
6158
6159out:
6160 return err_code;
6161}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162
6163/*
6164 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006165 * Returns the error code, 0 if OK, or any combination of :
6166 * - ERR_ABORT: must abort ASAP
6167 * - ERR_FATAL: we can continue parsing but not start the service
6168 * - ERR_WARN: a warning has been emitted
6169 * - ERR_ALERT: an alert has been emitted
6170 * Only the two first ones can stop processing, the two others are just
6171 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006173int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006175 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 FILE *f;
6177 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006179 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006180
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 if ((f=fopen(file,"r")) == NULL)
6182 return -1;
6183
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006184 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006185 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006186 char *end;
6187 char *args[MAX_LINE_ARGS + 1];
6188 char *line = thisline;
6189
Willy Tarreaubaaee002006-06-26 02:48:02 +02006190 linenum++;
6191
6192 end = line + strlen(line);
6193
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006194 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6195 /* Check if we reached the limit and the last char is not \n.
6196 * Watch out for the last line without the terminating '\n'!
6197 */
6198 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006199 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006200 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006201 }
6202
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006204 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 line++;
6206
6207 arg = 0;
6208 args[arg] = line;
6209
6210 while (*line && arg < MAX_LINE_ARGS) {
6211 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6212 * C equivalent value. Other combinations left unchanged (eg: \1).
6213 */
6214 if (*line == '\\') {
6215 int skip = 0;
6216 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6217 *line = line[1];
6218 skip = 1;
6219 }
6220 else if (line[1] == 'r') {
6221 *line = '\r';
6222 skip = 1;
6223 }
6224 else if (line[1] == 'n') {
6225 *line = '\n';
6226 skip = 1;
6227 }
6228 else if (line[1] == 't') {
6229 *line = '\t';
6230 skip = 1;
6231 }
6232 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006233 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006234 unsigned char hex1, hex2;
6235 hex1 = toupper(line[2]) - '0';
6236 hex2 = toupper(line[3]) - '0';
6237 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6238 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6239 *line = (hex1<<4) + hex2;
6240 skip = 3;
6241 }
6242 else {
6243 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006244 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 }
6246 }
6247 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006248 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006249 end -= skip;
6250 }
6251 line++;
6252 }
6253 else if (*line == '#' || *line == '\n' || *line == '\r') {
6254 /* end of string, end of loop */
6255 *line = 0;
6256 break;
6257 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006258 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006259 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006260 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006261 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006262 line++;
6263 args[++arg] = line;
6264 }
6265 else {
6266 line++;
6267 }
6268 }
6269
6270 /* empty line */
6271 if (!**args)
6272 continue;
6273
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006274 if (*line) {
6275 /* we had to stop due to too many args.
6276 * Let's terminate the string, print the offending part then cut the
6277 * last arg.
6278 */
6279 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6280 line++;
6281 *line = '\0';
6282
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006283 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006284 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006285 err_code |= ERR_ALERT | ERR_FATAL;
6286 args[arg] = line;
6287 }
6288
Willy Tarreau540abe42007-05-02 20:50:16 +02006289 /* zero out remaining args and ensure that at least one entry
6290 * is zeroed out.
6291 */
6292 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 args[arg] = line;
6294 }
6295
Willy Tarreau3842f002009-06-14 11:39:52 +02006296 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006297 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006298 char *tmp;
6299
Willy Tarreau3842f002009-06-14 11:39:52 +02006300 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006301 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006302 for (arg=0; *args[arg+1]; arg++)
6303 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006304 *tmp = '\0'; // fix the next arg to \0
6305 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006306 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006307 else if (!strcmp(args[0], "default")) {
6308 kwm = KWM_DEF;
6309 for (arg=0; *args[arg+1]; arg++)
6310 args[arg] = args[arg+1]; // shift args after inversion
6311 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006312
William Lallemand0f99e342011-10-12 17:50:54 +02006313 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6314 strcmp(args[0], "log") != 0) {
6315 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006316 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006317 }
6318
Willy Tarreau977b8e42006-12-29 14:19:17 +01006319 if (!strcmp(args[0], "listen") ||
6320 !strcmp(args[0], "frontend") ||
6321 !strcmp(args[0], "backend") ||
6322 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006323 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006325 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006326 cursection = strdup(args[0]);
6327 }
6328 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006330 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006331 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006332 }
6333 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006334 confsect = CFG_USERLIST;
6335 free(cursection);
6336 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006337 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006338 else if (!strcmp(args[0], "peers")) {
6339 confsect = CFG_PEERS;
6340 free(cursection);
6341 cursection = strdup(args[0]);
6342 }
6343
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 /* else it's a section keyword */
6345
6346 switch (confsect) {
6347 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006348 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006349 break;
6350 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006351 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006353 case CFG_USERLIST:
6354 err_code |= cfg_parse_users(file, linenum, args, kwm);
6355 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006356 case CFG_PEERS:
6357 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6358 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006360 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006361 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006363
6364 if (err_code & ERR_ABORT)
6365 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006366 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006367 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006368 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006370 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006371}
6372
Willy Tarreaubb925012009-07-23 13:36:36 +02006373/*
6374 * Returns the error code, 0 if OK, or any combination of :
6375 * - ERR_ABORT: must abort ASAP
6376 * - ERR_FATAL: we can continue parsing but not start the service
6377 * - ERR_WARN: a warning has been emitted
6378 * - ERR_ALERT: an alert has been emitted
6379 * Only the two first ones can stop processing, the two others are just
6380 * indicators.
6381 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006382int check_config_validity()
6383{
6384 int cfgerr = 0;
6385 struct proxy *curproxy = NULL;
6386 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006387 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006388 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006389 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006390 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006392 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 /*
6394 * Now, check for the integrity of all that we have collected.
6395 */
6396
6397 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006398 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399
Willy Tarreau193b8c62012-11-22 00:17:38 +01006400 if (!global.tune.max_http_hdr)
6401 global.tune.max_http_hdr = MAX_HTTP_HDR;
6402
6403 if (!global.tune.cookie_len)
6404 global.tune.cookie_len = CAPTURE_LEN;
6405
6406 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6407
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006408 /* first, we will invert the proxy list order */
6409 curproxy = NULL;
6410 while (proxy) {
6411 struct proxy *next;
6412
6413 next = proxy->next;
6414 proxy->next = curproxy;
6415 curproxy = proxy;
6416 if (!next)
6417 break;
6418 proxy = next;
6419 }
6420
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006422 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006423 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006424 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006425 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006426 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006427 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006428 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006429
Willy Tarreau050536d2012-10-04 08:47:34 +02006430 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006431 /* proxy ID not set, use automatic numbering with first
6432 * spare entry starting with next_pxid.
6433 */
6434 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6435 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6436 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006437 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006438 next_pxid++;
6439
Willy Tarreau55ea7572007-06-17 19:56:27 +02006440
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006442 /* ensure we don't keep listeners uselessly bound */
6443 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 curproxy = curproxy->next;
6445 continue;
6446 }
6447
Willy Tarreau16a21472012-11-19 12:39:59 +01006448 /* number of processes this proxy is bound to */
6449 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6450
Willy Tarreauff01a212009-03-15 13:46:16 +01006451 switch (curproxy->mode) {
6452 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006453 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006454 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006455 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6456 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006457 cfgerr++;
6458 }
6459
6460 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006461 Warning("config : servers will be ignored for %s '%s'.\n",
6462 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006463 break;
6464
6465 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006466 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006467 break;
6468
6469 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006470 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006471 break;
6472 }
6473
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006474 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006475 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006476 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006477 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6478 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006479 cfgerr++;
6480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006482 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006483 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6484 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006485 cfgerr++;
6486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006487#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006488 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006489 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6490 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006491 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006492 }
6493 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006494 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006495 /* If no LB algo is set in a backend, and we're not in
6496 * transparent mode, dispatch mode nor proxy mode, we
6497 * want to use balance roundrobin by default.
6498 */
6499 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6500 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006501 }
6502 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006503
Willy Tarreau1620ec32011-08-06 17:05:02 +02006504 if (curproxy->options & PR_O_DISPATCH)
6505 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6506 else if (curproxy->options & PR_O_HTTP_PROXY)
6507 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6508 else if (curproxy->options & PR_O_TRANSP)
6509 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006510
Willy Tarreau1620ec32011-08-06 17:05:02 +02006511 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6512 if (curproxy->options & PR_O_DISABLE404) {
6513 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6514 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6515 err_code |= ERR_WARN;
6516 curproxy->options &= ~PR_O_DISABLE404;
6517 }
6518 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6519 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6520 "send-state", proxy_type_str(curproxy), curproxy->id);
6521 err_code |= ERR_WARN;
6522 curproxy->options &= ~PR_O2_CHK_SNDST;
6523 }
Willy Tarreauef781042010-01-27 11:53:01 +01006524 }
6525
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006526 /* if a default backend was specified, let's find it */
6527 if (curproxy->defbe.name) {
6528 struct proxy *target;
6529
Alex Williams96532db2009-11-01 21:27:13 -05006530 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006531 if (!target) {
6532 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6533 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006534 cfgerr++;
6535 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006536 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6537 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006538 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006539 } else {
6540 free(curproxy->defbe.name);
6541 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006542 /* we force the backend to be present on at least all of
6543 * the frontend's processes.
6544 */
6545 target->bind_proc = curproxy->bind_proc ?
6546 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006547
6548 /* Emit a warning if this proxy also has some servers */
6549 if (curproxy->srv) {
6550 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6551 curproxy->id);
6552 err_code |= ERR_WARN;
6553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006554 }
6555 }
6556
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006557 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006558 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6559 /* map jump target for ACT_SETBE in req_rep chain */
6560 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006561 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006562 struct proxy *target;
6563
Willy Tarreaua496b602006-12-17 23:15:24 +01006564 if (exp->action != ACT_SETBE)
6565 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006566
Alex Williams96532db2009-11-01 21:27:13 -05006567 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006568 if (!target) {
6569 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6570 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006571 cfgerr++;
6572 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006573 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6574 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006575 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006576 } else {
6577 free((void *)exp->replace);
6578 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006579 /* we force the backend to be present on at least all of
6580 * the frontend's processes.
6581 */
6582 target->bind_proc = curproxy->bind_proc ?
6583 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006584 }
6585 }
6586 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006587
6588 /* find the target proxy for 'use_backend' rules */
6589 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006590 struct proxy *target;
6591
Alex Williams96532db2009-11-01 21:27:13 -05006592 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006593
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006594 if (!target) {
6595 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6596 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006597 cfgerr++;
6598 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006599 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6600 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006601 cfgerr++;
6602 } else {
6603 free((void *)rule->be.name);
6604 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006605 /* we force the backend to be present on at least all of
6606 * the frontend's processes.
6607 */
6608 target->bind_proc = curproxy->bind_proc ?
6609 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006610 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006611 }
6612
6613 /* find the target proxy for 'use_backend' rules */
6614 list_for_each_entry(srule, &curproxy->server_rules, list) {
6615 struct server *target = findserver(curproxy, srule->srv.name);
6616
6617 if (!target) {
6618 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6619 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6620 cfgerr++;
6621 continue;
6622 }
6623 free((void *)srule->srv.name);
6624 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006625 }
6626
Emeric Brunb982a3d2010-01-04 15:45:53 +01006627 /* find the target table for 'stick' rules */
6628 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6629 struct proxy *target;
6630
Emeric Brun1d33b292010-01-04 15:47:17 +01006631 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6632 if (mrule->flags & STK_IS_STORE)
6633 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6634
Emeric Brunb982a3d2010-01-04 15:45:53 +01006635 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006636 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006637 else
6638 target = curproxy;
6639
6640 if (!target) {
6641 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6642 curproxy->id, mrule->table.name);
6643 cfgerr++;
6644 }
6645 else if (target->table.size == 0) {
6646 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6647 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6648 cfgerr++;
6649 }
Willy Tarreau12785782012-04-27 21:37:17 +02006650 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6651 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006652 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6653 cfgerr++;
6654 }
6655 else {
6656 free((void *)mrule->table.name);
6657 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006658 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006659 }
6660 }
6661
6662 /* find the target table for 'store response' rules */
6663 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6664 struct proxy *target;
6665
Emeric Brun1d33b292010-01-04 15:47:17 +01006666 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6667
Emeric Brunb982a3d2010-01-04 15:45:53 +01006668 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006669 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006670 else
6671 target = curproxy;
6672
6673 if (!target) {
6674 Alert("Proxy '%s': unable to find store table '%s'.\n",
6675 curproxy->id, mrule->table.name);
6676 cfgerr++;
6677 }
6678 else if (target->table.size == 0) {
6679 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6680 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6681 cfgerr++;
6682 }
Willy Tarreau12785782012-04-27 21:37:17 +02006683 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6684 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006685 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6686 cfgerr++;
6687 }
6688 else {
6689 free((void *)mrule->table.name);
6690 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006691 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006692 }
6693 }
6694
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006695 /* find the target table for 'tcp-request' layer 4 rules */
6696 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6697 struct proxy *target;
6698
Willy Tarreaub4c84932013-07-23 19:15:30 +02006699 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006700 continue;
6701
6702 if (trule->act_prm.trk_ctr.table.n)
6703 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6704 else
6705 target = curproxy;
6706
6707 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006708 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6709 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006710 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006711 cfgerr++;
6712 }
6713 else if (target->table.size == 0) {
6714 Alert("Proxy '%s': table '%s' used but not configured.\n",
6715 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6716 cfgerr++;
6717 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006718 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6719 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6720 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 +01006721 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006722 cfgerr++;
6723 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006724 else {
6725 free(trule->act_prm.trk_ctr.table.n);
6726 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006727 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006728 * to pass a list of counters to track and allocate them right here using
6729 * stktable_alloc_data_type().
6730 */
6731 }
6732 }
6733
Willy Tarreaud1f96522010-08-03 19:34:32 +02006734 /* find the target table for 'tcp-request' layer 6 rules */
6735 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6736 struct proxy *target;
6737
Willy Tarreaub4c84932013-07-23 19:15:30 +02006738 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006739 continue;
6740
6741 if (trule->act_prm.trk_ctr.table.n)
6742 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6743 else
6744 target = curproxy;
6745
6746 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006747 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6748 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006749 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006750 cfgerr++;
6751 }
6752 else if (target->table.size == 0) {
6753 Alert("Proxy '%s': table '%s' used but not configured.\n",
6754 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6755 cfgerr++;
6756 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006757 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6758 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6759 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 +01006760 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006761 cfgerr++;
6762 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006763 else {
6764 free(trule->act_prm.trk_ctr.table.n);
6765 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006766 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006767 * to pass a list of counters to track and allocate them right here using
6768 * stktable_alloc_data_type().
6769 */
6770 }
6771 }
6772
Emeric Brun32da3c42010-09-23 18:39:19 +02006773 if (curproxy->table.peers.name) {
6774 struct peers *curpeers = peers;
6775
6776 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6777 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6778 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006779 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006780 break;
6781 }
6782 }
6783
6784 if (!curpeers) {
6785 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6786 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006787 free((void *)curproxy->table.peers.name);
6788 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006789 cfgerr++;
6790 }
6791 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006792 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6793 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006794 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006795 cfgerr++;
6796 }
6797 }
6798
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006799 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006800 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006801 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6802 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6803 "proxy", curproxy->id);
6804 cfgerr++;
6805 goto out_uri_auth_compat;
6806 }
6807
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006808 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006809 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006810 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006811 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006812
Willy Tarreau95fa4692010-02-01 13:05:50 +01006813 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6814 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006815
6816 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006817 uri_auth_compat_req[i++] = "realm";
6818 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6819 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006820
Willy Tarreau95fa4692010-02-01 13:05:50 +01006821 uri_auth_compat_req[i++] = "unless";
6822 uri_auth_compat_req[i++] = "{";
6823 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6824 uri_auth_compat_req[i++] = "}";
6825 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006826
Willy Tarreauff011f22011-01-06 17:51:27 +01006827 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6828 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006829 cfgerr++;
6830 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006831 }
6832
Willy Tarreauff011f22011-01-06 17:51:27 +01006833 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006834
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006835 if (curproxy->uri_auth->auth_realm) {
6836 free(curproxy->uri_auth->auth_realm);
6837 curproxy->uri_auth->auth_realm = NULL;
6838 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006839
6840 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006841 }
6842out_uri_auth_compat:
6843
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006844 /* compile the log format */
6845 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006846 if (curproxy->conf.logformat_string != default_http_log_format &&
6847 curproxy->conf.logformat_string != default_tcp_log_format &&
6848 curproxy->conf.logformat_string != clf_http_log_format)
6849 free(curproxy->conf.logformat_string);
6850 curproxy->conf.logformat_string = NULL;
6851 free(curproxy->conf.lfs_file);
6852 curproxy->conf.lfs_file = NULL;
6853 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006854 }
6855
Willy Tarreau62a61232013-04-12 18:13:46 +02006856 if (curproxy->conf.logformat_string) {
6857 curproxy->conf.args.ctx = ARGC_LOG;
6858 curproxy->conf.args.file = curproxy->conf.lfs_file;
6859 curproxy->conf.args.line = curproxy->conf.lfs_line;
6860 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006861 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006862 curproxy->conf.args.file = NULL;
6863 curproxy->conf.args.line = 0;
6864 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006865
Willy Tarreau62a61232013-04-12 18:13:46 +02006866 if (curproxy->conf.uniqueid_format_string) {
6867 curproxy->conf.args.ctx = ARGC_UIF;
6868 curproxy->conf.args.file = curproxy->conf.uif_file;
6869 curproxy->conf.args.line = curproxy->conf.uif_line;
6870 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006871 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006872 curproxy->conf.args.file = NULL;
6873 curproxy->conf.args.line = 0;
6874 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006875
6876 /* only now we can check if some args remain unresolved */
6877 cfgerr += smp_resolve_args(curproxy);
6878 if (!cfgerr)
6879 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006880
Willy Tarreau2738a142006-07-08 17:28:09 +02006881 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006882 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006883 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006884 (!curproxy->timeout.connect ||
6885 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006886 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006887 " | While not properly invalid, you will certainly encounter various problems\n"
6888 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006889 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006890 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006891 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006892 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006893
Willy Tarreau1fa31262007-12-03 00:36:16 +01006894 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6895 * We must still support older configurations, so let's find out whether those
6896 * parameters have been set or must be copied from contimeouts.
6897 */
6898 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006899 if (!curproxy->timeout.tarpit ||
6900 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006901 /* tarpit timeout not set. We search in the following order:
6902 * default.tarpit, curr.connect, default.connect.
6903 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006904 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006905 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006906 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006907 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006908 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006909 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006910 }
6911 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006912 (!curproxy->timeout.queue ||
6913 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006914 /* queue timeout not set. We search in the following order:
6915 * default.queue, curr.connect, default.connect.
6916 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006917 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006918 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006919 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006920 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006921 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006922 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006923 }
6924 }
6925
Willy Tarreau1620ec32011-08-06 17:05:02 +02006926 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006927 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6928 curproxy->check_req = (char *)malloc(curproxy->check_len);
6929 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006930 }
6931
Willy Tarreau193b8c62012-11-22 00:17:38 +01006932 /* ensure that cookie capture length is not too large */
6933 if (curproxy->capture_len >= global.tune.cookie_len) {
6934 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6935 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6936 err_code |= ERR_WARN;
6937 curproxy->capture_len = global.tune.cookie_len - 1;
6938 }
6939
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006940 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006941 if (curproxy->nb_req_cap) {
6942 if (curproxy->mode == PR_MODE_HTTP) {
6943 curproxy->req_cap_pool = create_pool("ptrcap",
6944 curproxy->nb_req_cap * sizeof(char *),
6945 MEM_F_SHARED);
6946 } else {
6947 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6948 proxy_type_str(curproxy), curproxy->id);
6949 err_code |= ERR_WARN;
6950 curproxy->to_log &= ~LW_REQHDR;
6951 curproxy->nb_req_cap = 0;
6952 }
6953 }
6954
6955 if (curproxy->nb_rsp_cap) {
6956 if (curproxy->mode == PR_MODE_HTTP) {
6957 curproxy->rsp_cap_pool = create_pool("ptrcap",
6958 curproxy->nb_rsp_cap * sizeof(char *),
6959 MEM_F_SHARED);
6960 } else {
6961 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6962 proxy_type_str(curproxy), curproxy->id);
6963 err_code |= ERR_WARN;
6964 curproxy->to_log &= ~LW_REQHDR;
6965 curproxy->nb_rsp_cap = 0;
6966 }
6967 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006968
Willy Tarreaubaaee002006-06-26 02:48:02 +02006969 /* first, we will invert the servers list order */
6970 newsrv = NULL;
6971 while (curproxy->srv) {
6972 struct server *next;
6973
6974 next = curproxy->srv->next;
6975 curproxy->srv->next = newsrv;
6976 newsrv = curproxy->srv;
6977 if (!next)
6978 break;
6979 curproxy->srv = next;
6980 }
6981
Willy Tarreau17edc812014-01-03 12:14:34 +01006982 /* Check that no server name conflicts. This causes trouble in the stats.
6983 * We only emit a warning for the first conflict affecting each server,
6984 * in order to avoid combinatory explosion if all servers have the same
6985 * name. We do that only for servers which do not have an explicit ID,
6986 * because these IDs were made also for distinguishing them and we don't
6987 * want to annoy people who correctly manage them.
6988 */
6989 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6990 struct server *other_srv;
6991
6992 if (newsrv->puid)
6993 continue;
6994
6995 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6996 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6997 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6998 newsrv->conf.file, newsrv->conf.line,
6999 proxy_type_str(curproxy), curproxy->id,
7000 newsrv->id, other_srv->conf.line);
7001 break;
7002 }
7003 }
7004 }
7005
Willy Tarreaudd701652010-05-25 23:03:02 +02007006 /* assign automatic UIDs to servers which don't have one yet */
7007 next_id = 1;
7008 newsrv = curproxy->srv;
7009 while (newsrv != NULL) {
7010 if (!newsrv->puid) {
7011 /* server ID not set, use automatic numbering with first
7012 * spare entry starting with next_svid.
7013 */
7014 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7015 newsrv->conf.id.key = newsrv->puid = next_id;
7016 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7017 }
7018 next_id++;
7019 newsrv = newsrv->next;
7020 }
7021
Willy Tarreau20697042007-11-15 23:26:18 +01007022 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007023 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007024
Willy Tarreau62c3be22012-01-20 13:12:32 +01007025 /*
7026 * If this server supports a maxconn parameter, it needs a dedicated
7027 * tasks to fill the emptied slots when a connection leaves.
7028 * Also, resolve deferred tracking dependency if needed.
7029 */
7030 newsrv = curproxy->srv;
7031 while (newsrv != NULL) {
7032 if (newsrv->minconn > newsrv->maxconn) {
7033 /* Only 'minconn' was specified, or it was higher than or equal
7034 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7035 * this will avoid further useless expensive computations.
7036 */
7037 newsrv->maxconn = newsrv->minconn;
7038 } else if (newsrv->maxconn && !newsrv->minconn) {
7039 /* minconn was not specified, so we set it to maxconn */
7040 newsrv->minconn = newsrv->maxconn;
7041 }
7042
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007043#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007044 if (newsrv->use_ssl || newsrv->check.use_ssl)
7045 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007046#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007047
Willy Tarreau2f075e92013-12-03 11:11:34 +01007048 /* set the check type on the server */
7049 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7050
Willy Tarreau62c3be22012-01-20 13:12:32 +01007051 if (newsrv->trackit) {
7052 struct proxy *px;
7053 struct server *srv;
7054 char *pname, *sname;
7055
7056 pname = newsrv->trackit;
7057 sname = strrchr(pname, '/');
7058
7059 if (sname)
7060 *sname++ = '\0';
7061 else {
7062 sname = pname;
7063 pname = NULL;
7064 }
7065
7066 if (pname) {
7067 px = findproxy(pname, PR_CAP_BE);
7068 if (!px) {
7069 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7070 proxy_type_str(curproxy), curproxy->id,
7071 newsrv->id, pname);
7072 cfgerr++;
7073 goto next_srv;
7074 }
7075 } else
7076 px = curproxy;
7077
7078 srv = findserver(px, sname);
7079 if (!srv) {
7080 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7081 proxy_type_str(curproxy), curproxy->id,
7082 newsrv->id, sname);
7083 cfgerr++;
7084 goto next_srv;
7085 }
7086
Willy Tarreauff5ae352013-12-11 20:36:34 +01007087 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007088 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7089 "tracking as it does not have checks enabled.\n",
7090 proxy_type_str(curproxy), curproxy->id,
7091 newsrv->id, px->id, srv->id);
7092 cfgerr++;
7093 goto next_srv;
7094 }
7095
7096 if (curproxy != px &&
7097 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7098 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7099 "tracking: disable-on-404 option inconsistency.\n",
7100 proxy_type_str(curproxy), curproxy->id,
7101 newsrv->id, px->id, srv->id);
7102 cfgerr++;
7103 goto next_srv;
7104 }
7105
7106 /* if the other server is forced disabled, we have to do the same here */
7107 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007108 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007109 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007110 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007111 }
7112
7113 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007114 newsrv->tracknext = srv->trackers;
7115 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007116
7117 free(newsrv->trackit);
7118 newsrv->trackit = NULL;
7119 }
7120 next_srv:
7121 newsrv = newsrv->next;
7122 }
7123
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007124 /* We have to initialize the server lookup mechanism depending
7125 * on what LB algorithm was choosen.
7126 */
7127
7128 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7129 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7130 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007131 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7132 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7133 init_server_map(curproxy);
7134 } else {
7135 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7136 fwrr_init_server_groups(curproxy);
7137 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007138 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007139
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007140 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007141 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7142 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7143 fwlc_init_server_tree(curproxy);
7144 } else {
7145 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7146 fas_init_server_tree(curproxy);
7147 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007148 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007149
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007150 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007151 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7152 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7153 chash_init_server_tree(curproxy);
7154 } else {
7155 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7156 init_server_map(curproxy);
7157 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007158 break;
7159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007160
7161 if (curproxy->options & PR_O_LOGASAP)
7162 curproxy->to_log &= ~LW_BYTES;
7163
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007164 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007165 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007166 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7167 proxy_type_str(curproxy), curproxy->id);
7168 err_code |= ERR_WARN;
7169 }
7170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007171 if (curproxy->mode != PR_MODE_HTTP) {
7172 int optnum;
7173
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007174 if (curproxy->uri_auth) {
7175 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7176 proxy_type_str(curproxy), curproxy->id);
7177 err_code |= ERR_WARN;
7178 curproxy->uri_auth = NULL;
7179 }
7180
Willy Tarreau87cf5142011-08-19 22:57:24 +02007181 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007182 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7183 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7184 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007185 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007186 }
7187
7188 if (curproxy->options & PR_O_ORGTO) {
7189 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7190 "originalto", proxy_type_str(curproxy), curproxy->id);
7191 err_code |= ERR_WARN;
7192 curproxy->options &= ~PR_O_ORGTO;
7193 }
7194
7195 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7196 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7197 (curproxy->cap & cfg_opts[optnum].cap) &&
7198 (curproxy->options & cfg_opts[optnum].val)) {
7199 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7200 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7201 err_code |= ERR_WARN;
7202 curproxy->options &= ~cfg_opts[optnum].val;
7203 }
7204 }
7205
7206 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7207 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7208 (curproxy->cap & cfg_opts2[optnum].cap) &&
7209 (curproxy->options2 & cfg_opts2[optnum].val)) {
7210 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7211 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7212 err_code |= ERR_WARN;
7213 curproxy->options2 &= ~cfg_opts2[optnum].val;
7214 }
7215 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007216
Pieter Baauwd551fb52013-05-08 22:49:23 +02007217#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007218 if (curproxy->conn_src.bind_hdr_occ) {
7219 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007220 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007221 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007222 err_code |= ERR_WARN;
7223 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007224#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007225 }
7226
Willy Tarreaubaaee002006-06-26 02:48:02 +02007227 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007228 * ensure that we're not cross-dressing a TCP server into HTTP.
7229 */
7230 newsrv = curproxy->srv;
7231 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007232 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007233 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7234 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007235 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007236 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007237
Willy Tarreau0cec3312011-10-31 13:49:26 +01007238 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7239 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7240 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7241 err_code |= ERR_WARN;
7242 }
7243
Willy Tarreau82ffa392013-08-13 17:19:08 +02007244 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7245 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7246 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7247 err_code |= ERR_WARN;
7248 }
7249
Pieter Baauwd551fb52013-05-08 22:49:23 +02007250#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007251 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7252 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007253 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 +01007254 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007255 err_code |= ERR_WARN;
7256 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007257#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007258 newsrv = newsrv->next;
7259 }
7260
Willy Tarreauc1a21672009-08-16 22:37:44 +02007261 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007262 if (!curproxy->accept)
7263 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007264
Willy Tarreauc1a21672009-08-16 22:37:44 +02007265 if (curproxy->tcp_req.inspect_delay ||
7266 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007267 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007268
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007269 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007270 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007271 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007272 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007273
7274 /* both TCP and HTTP must check switching rules */
7275 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7276 }
7277
7278 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007279 if (curproxy->tcp_req.inspect_delay ||
7280 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7281 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7282
Emeric Brun97679e72010-09-23 17:56:44 +02007283 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7284 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7285
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007286 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007287 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007288 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007289 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007290
7291 /* If the backend does requires RDP cookie persistence, we have to
7292 * enable the corresponding analyser.
7293 */
7294 if (curproxy->options2 & PR_O2_RDPC_PRST)
7295 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7296 }
7297
Emeric Brunc52962f2012-11-15 18:28:02 +01007298#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007299 /* Configure SSL for each bind line.
7300 * Note: if configuration fails at some point, the ->ctx member
7301 * remains NULL so that listeners can later detach.
7302 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007303 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007304 if (!bind_conf->is_ssl) {
7305 if (bind_conf->default_ctx) {
7306 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7307 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7308 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007309 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007310 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007311 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007312 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007313 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007314 cfgerr++;
7315 continue;
7316 }
7317
Emeric Brun4b3091e2012-09-24 15:48:52 +02007318 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007319 Alert("Unable to allocate SSL session cache.\n");
7320 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007321 continue;
7322 }
7323
Emeric Brunfc0421f2012-09-07 17:30:07 +02007324 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007325 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007326 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007327#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007328
Willy Tarreaue6b98942007-10-29 01:09:36 +01007329 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007330 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007331 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007332 if (!listener->luid) {
7333 /* listener ID not set, use automatic numbering with first
7334 * spare entry starting with next_luid.
7335 */
7336 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7337 listener->conf.id.key = listener->luid = next_id;
7338 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007339 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007340 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007341
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007342 /* enable separate counters */
7343 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7344 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007345 if (!listener->name)
7346 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007347 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007348
Willy Tarreaue6b98942007-10-29 01:09:36 +01007349 if (curproxy->options & PR_O_TCP_NOLING)
7350 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007351 if (!listener->maxconn)
7352 listener->maxconn = curproxy->maxconn;
7353 if (!listener->backlog)
7354 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007355 if (!listener->maxaccept)
7356 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7357
7358 /* we want to have an optimal behaviour on single process mode to
7359 * maximize the work at once, but in multi-process we want to keep
7360 * some fairness between processes, so we target half of the max
7361 * number of events to be balanced over all the processes the proxy
7362 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7363 * used to disable the limit.
7364 */
7365 if (listener->maxaccept > 0) {
7366 if (nbproc > 1)
7367 listener->maxaccept = (listener->maxaccept + 1) / 2;
7368 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7369 }
7370
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007371 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007372 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007373 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007374 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007375
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007376 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7377 listener->options |= LI_O_TCP_RULES;
7378
Willy Tarreaude3041d2010-05-31 10:56:17 +02007379 if (curproxy->mon_mask.s_addr)
7380 listener->options |= LI_O_CHK_MONNET;
7381
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007382 /* smart accept mode is automatic in HTTP mode */
7383 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007384 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007385 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7386 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007387 }
7388
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007389 /* Release unused SSL configs */
7390 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7391 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007392 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007393#ifdef USE_OPENSSL
7394 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007395 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007396 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007397 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007398 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007399#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007400 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007401
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007402 /* Check multi-process mode compatibility for the current proxy */
7403 if (global.nbproc > 1) {
7404 int nbproc = 0;
7405 if (curproxy->bind_proc) {
7406 int proc;
7407 for (proc = 0; proc < global.nbproc; proc++) {
7408 if (curproxy->bind_proc & (1 << proc)) {
7409 nbproc++;
7410 }
7411 }
7412 } else {
7413 nbproc = global.nbproc;
7414 }
7415 if (curproxy->table.peers.name) {
7416 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7417 curproxy->id);
7418 cfgerr++;
7419 }
7420 if (nbproc > 1) {
7421 if (curproxy->uri_auth) {
7422 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7423 curproxy->id);
7424 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7425 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7426 curproxy->id);
7427 }
7428 }
7429 if (curproxy->appsession_name) {
7430 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7431 curproxy->id);
7432 }
7433 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7434 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7435 curproxy->id);
7436 }
7437 }
7438 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007439
7440 /* create the task associated with the proxy */
7441 curproxy->task = task_new();
7442 if (curproxy->task) {
7443 curproxy->task->context = curproxy;
7444 curproxy->task->process = manage_proxy;
7445 /* no need to queue, it will be done automatically if some
7446 * listener gets limited.
7447 */
7448 curproxy->task->expire = TICK_ETERNITY;
7449 } else {
7450 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7451 curproxy->id);
7452 cfgerr++;
7453 }
7454
Willy Tarreaubaaee002006-06-26 02:48:02 +02007455 curproxy = curproxy->next;
7456 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007457
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007458 /* Check multi-process mode compatibility */
7459 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007460 if (global.stats_fe && !global.stats_fe->bind_proc) {
7461 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 +01007462 }
7463 }
7464
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007465 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7466 struct auth_users *curuser;
7467 int g;
7468
7469 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7470 unsigned int group_mask = 0;
7471 char *group = NULL;
7472
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007473 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007474 continue;
7475
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007476 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007477
7478 for (g = 0; g < curuserlist->grpcnt; g++)
7479 if (!strcmp(curuserlist->groups[g], group))
7480 break;
7481
7482 if (g == curuserlist->grpcnt) {
7483 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7484 curuserlist->name, group, curuser->user);
7485 err_code |= ERR_ALERT | ERR_FATAL;
7486 goto out;
7487 }
7488
7489 group_mask |= (1 << g);
7490 }
7491
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007492 free(curuser->u.groups);
7493 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007494 }
7495
7496 for (g = 0; g < curuserlist->grpcnt; g++) {
7497 char *user = NULL;
7498
7499 if (!curuserlist->groupusers[g])
7500 continue;
7501
7502 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7503 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7504 if (!strcmp(curuser->user, user))
7505 break;
7506
7507 if (!curuser) {
7508 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7509 curuserlist->name, user, curuserlist->groups[g]);
7510 err_code |= ERR_ALERT | ERR_FATAL;
7511 goto out;
7512 }
7513
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007514 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007515 }
7516
7517 free(curuserlist->groupusers[g]);
7518 }
7519
7520 free(curuserlist->groupusers);
7521
7522#ifdef DEBUG_AUTH
7523 for (g = 0; g < curuserlist->grpcnt; g++) {
7524 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7525
7526 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007527 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007528 fprintf(stderr, " %s", curuser->user);
7529 }
7530
7531 fprintf(stderr, "\n");
7532 }
7533#endif
7534
Willy Tarreaufbb78422011-06-05 15:38:35 +02007535 }
7536
7537 /* automatically compute fullconn if not set. We must not do it in the
7538 * loop above because cross-references are not yet fully resolved.
7539 */
7540 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7541 /* If <fullconn> is not set, let's set it to 10% of the sum of
7542 * the possible incoming frontend's maxconns.
7543 */
7544 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7545 struct proxy *fe;
7546 int total = 0;
7547
7548 /* sum up the number of maxconns of frontends which
7549 * reference this backend at least once or which are
7550 * the same one ('listen').
7551 */
7552 for (fe = proxy; fe; fe = fe->next) {
7553 struct switching_rule *rule;
7554 struct hdr_exp *exp;
7555 int found = 0;
7556
7557 if (!(fe->cap & PR_CAP_FE))
7558 continue;
7559
7560 if (fe == curproxy) /* we're on a "listen" instance */
7561 found = 1;
7562
7563 if (fe->defbe.be == curproxy) /* "default_backend" */
7564 found = 1;
7565
7566 /* check if a "use_backend" rule matches */
7567 if (!found) {
7568 list_for_each_entry(rule, &fe->switching_rules, list) {
7569 if (rule->be.backend == curproxy) {
7570 found = 1;
7571 break;
7572 }
7573 }
7574 }
7575
7576 /* check if a "reqsetbe" rule matches */
7577 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7578 if (exp->action == ACT_SETBE &&
7579 (struct proxy *)exp->replace == curproxy) {
7580 found = 1;
7581 break;
7582 }
7583 }
7584
7585 /* now we've checked all possible ways to reference a backend
7586 * from a frontend.
7587 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007588 if (!found)
7589 continue;
7590 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007591 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007592 /* we have the sum of the maxconns in <total>. We only
7593 * keep 10% of that sum to set the default fullconn, with
7594 * a hard minimum of 1 (to avoid a divide by zero).
7595 */
7596 curproxy->fullconn = (total + 9) / 10;
7597 if (!curproxy->fullconn)
7598 curproxy->fullconn = 1;
7599 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007600 }
7601
Willy Tarreau056f5682010-06-06 15:51:11 +02007602 /* initialize stick-tables on backend capable proxies. This must not
7603 * be done earlier because the data size may be discovered while parsing
7604 * other proxies.
7605 */
Godbach9703e662013-12-11 21:11:41 +08007606 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7607 if (!stktable_init(&curproxy->table)) {
7608 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7609 cfgerr++;
7610 }
7611 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007612
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007613 /*
7614 * Recount currently required checks.
7615 */
7616
7617 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7618 int optnum;
7619
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007620 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7621 if (curproxy->options & cfg_opts[optnum].val)
7622 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007623
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007624 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7625 if (curproxy->options2 & cfg_opts2[optnum].val)
7626 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007627 }
7628
Willy Tarreau122541c2011-09-07 21:24:49 +02007629 if (peers) {
7630 struct peers *curpeers = peers, **last;
7631 struct peer *p, *pb;
7632
7633 /* Remove all peers sections which don't have a valid listener.
7634 * This can happen when a peers section is never referenced and
7635 * does not contain a local peer.
7636 */
7637 last = &peers;
7638 while (*last) {
7639 curpeers = *last;
7640 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007641 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007642 last = &curpeers->next;
7643 continue;
7644 }
7645
7646 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7647 curpeers->id, localpeer);
7648
7649 p = curpeers->remote;
7650 while (p) {
7651 pb = p->next;
7652 free(p->id);
7653 free(p);
7654 p = pb;
7655 }
7656
7657 /* Destroy and unlink this curpeers section.
7658 * Note: curpeers is backed up into *last.
7659 */
7660 free(curpeers->id);
7661 curpeers = curpeers->next;
7662 free(*last);
7663 *last = curpeers;
7664 }
7665 }
7666
Willy Tarreau34eb6712011-10-24 18:15:04 +02007667 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007668 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007669 MEM_F_SHARED);
7670
Willy Tarreaubb925012009-07-23 13:36:36 +02007671 if (cfgerr > 0)
7672 err_code |= ERR_ALERT | ERR_FATAL;
7673 out:
7674 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007675}
7676
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007677/*
7678 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7679 * parsing sessions.
7680 */
7681void cfg_register_keywords(struct cfg_kw_list *kwl)
7682{
7683 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7684}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007685
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007686/*
7687 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7688 */
7689void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7690{
7691 LIST_DEL(&kwl->list);
7692 LIST_INIT(&kwl->list);
7693}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007694
7695/*
7696 * Local variables:
7697 * c-indent-level: 8
7698 * c-basic-offset: 8
7699 * End:
7700 */