blob: a24eda8aa66f6d239b285c08aeec2fed69fac8ec [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 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100133 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int 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 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100206 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100207 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
209 str = next;
210 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100211 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 *next++ = 0;
213 }
214
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100215 ss2 = str2sa_range(str, &port, &end, err,
216 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
217 if (!ss2)
218 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100220 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100221 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100226 if (!port || !end) {
227 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
228 goto fail;
229 }
230
Emeric Bruned760922010-10-22 17:59:25 +0200231 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200232 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200233 goto fail;
234 }
235
236 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200237 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200238 goto fail;
239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100241 else if (ss2->ss_family == AF_UNSPEC) {
242 socklen_t addr_len;
243
244 /* We want to attach to an already bound fd whose number
245 * is in the addr part of ss2 when cast to sockaddr_in.
246 * Note that by definition there is a single listener.
247 * We still have to determine the address family to
248 * register the correct protocol.
249 */
250 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
251 addr_len = sizeof(*ss2);
252 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
253 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
254 goto fail;
255 }
256
257 port = end = get_host_port(ss2);
258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100260 /* OK the address looks correct */
261 ss = *ss2;
262
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 for (; port <= end; port++) {
264 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100265 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau40aa0702013-03-10 23:51:38 +0100271 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200273 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100414/* Report it if a request ACL condition uses some keywords that are incompatible
415 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
416 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
417 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100419static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100420{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100421 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200422 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100425 return 0;
426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 acl = acl_cond_conflicts(cond, where);
428 if (acl) {
429 if (acl->name && *acl->name)
430 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
431 file, line, acl->name, sample_ckp_names(where));
432 else
433 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 +0200434 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100435 return ERR_WARN;
436 }
437 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100438 return 0;
439
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100440 if (acl->name && *acl->name)
441 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200442 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 else
444 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100446 return ERR_WARN;
447}
448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200468 else if (!strcmp(args[0], "ca-base")) {
469#ifdef USE_OPENSSL
470 if (global.ca_base != NULL) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT;
473 goto out;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
479 }
480 global.ca_base = strdup(args[1]);
481#else
482 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
485#endif
486 }
487 else if (!strcmp(args[0], "crt-base")) {
488#ifdef USE_OPENSSL
489 if (global.crt_base != NULL) {
490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
491 err_code |= ERR_ALERT;
492 goto out;
493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
498 }
499 global.crt_base = strdup(args[1]);
500#else
501 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504#endif
505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200506 else if (!strcmp(args[0], "daemon")) {
507 global.mode |= MODE_DAEMON;
508 }
509 else if (!strcmp(args[0], "debug")) {
510 global.mode |= MODE_DEBUG;
511 }
512 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100513 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200515 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100521 else if (!strcmp(args[0], "nosplice")) {
522 global.tune.options &= ~GTUNE_USE_SPLICE;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 else if (!strcmp(args[0], "quiet")) {
525 global.mode |= MODE_QUIET;
526 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200527 else if (!strcmp(args[0], "tune.maxpollevents")) {
528 if (global.tune.maxpollevents != 0) {
529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 err_code |= ERR_ALERT;
531 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 }
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 global.tune.maxpollevents = atol(args[1]);
539 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100540 else if (!strcmp(args[0], "tune.maxaccept")) {
541 if (global.tune.maxaccept != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 err_code |= ERR_ALERT;
544 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 global.tune.maxaccept = atol(args[1]);
552 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200553 else if (!strcmp(args[0], "tune.chksize")) {
554 if (*(args[1]) == 0) {
555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT | ERR_FATAL;
557 goto out;
558 }
559 global.tune.chksize = atol(args[1]);
560 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200561#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100562 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.sslcachesize = atol(args[1]);
569 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100570 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
571 unsigned int ssllifetime;
572 const char *res;
573
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579
580 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
581 if (res) {
582 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
583 file, linenum, *res, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587
588 global.tune.ssllifetime = ssllifetime;
589 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100590 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.tune.ssl_max_record = atol(args[1]);
597 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200599 else if (!strcmp(args[0], "tune.bufsize")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.bufsize = atol(args[1]);
606 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
607 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100608 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100609 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200610 }
611 else if (!strcmp(args[0], "tune.maxrewrite")) {
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617 global.tune.maxrewrite = atol(args[1]);
618 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
619 global.tune.maxrewrite = global.tune.bufsize / 2;
620 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100621 else if (!strcmp(args[0], "tune.idletimer")) {
622 unsigned int idle;
623 const char *res;
624
625 if (*(args[1]) == 0) {
626 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT | ERR_FATAL;
628 goto out;
629 }
630
631 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
632 if (res) {
633 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
634 file, linenum, *res, args[0]);
635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
637 }
638
639 if (idle > 65535) {
640 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.idle_timer = idle;
645 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100646 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
647 if (global.tune.client_rcvbuf != 0) {
648 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT;
650 goto out;
651 }
652 if (*(args[1]) == 0) {
653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656 }
657 global.tune.client_rcvbuf = atol(args[1]);
658 }
659 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
660 if (global.tune.server_rcvbuf != 0) {
661 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT;
663 goto out;
664 }
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
669 }
670 global.tune.server_rcvbuf = atol(args[1]);
671 }
672 else if (!strcmp(args[0], "tune.sndbuf.client")) {
673 if (global.tune.client_sndbuf != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT;
676 goto out;
677 }
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.client_sndbuf = atol(args[1]);
684 }
685 else if (!strcmp(args[0], "tune.sndbuf.server")) {
686 if (global.tune.server_sndbuf != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT;
689 goto out;
690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 global.tune.server_sndbuf = atol(args[1]);
697 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200698 else if (!strcmp(args[0], "tune.pipesize")) {
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.pipesize = atol(args[1]);
705 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100706 else if (!strcmp(args[0], "tune.http.cookielen")) {
707 if (*(args[1]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712 global.tune.cookie_len = atol(args[1]) + 1;
713 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200714 else if (!strcmp(args[0], "tune.http.maxhdr")) {
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.max_http_hdr = atol(args[1]);
721 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100722 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
723#ifdef USE_ZLIB
724 if (*args[1]) {
725 global.tune.zlibmemlevel = atoi(args[1]);
726 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
727 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
728 file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 } else {
733 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
734 file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#else
739 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742#endif
743 }
744 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
745#ifdef USE_ZLIB
746 if (*args[1]) {
747 global.tune.zlibwindowsize = atoi(args[1]);
748 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
749 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\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 8 and 15\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760#else
761 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764#endif
765 }
William Lallemandf3747832012-11-09 12:33:10 +0100766 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
767 if (*args[1]) {
768 global.tune.comp_maxlevel = atoi(args[1]);
769 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
770 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
771 file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 } else {
776 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
777 file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 else if (!strcmp(args[0], "uid")) {
783 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200784 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT;
786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 }
788 if (*(args[1]) == 0) {
789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 }
793 global.uid = atol(args[1]);
794 }
795 else if (!strcmp(args[0], "gid")) {
796 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200797 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200798 err_code |= ERR_ALERT;
799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 }
801 if (*(args[1]) == 0) {
802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 }
806 global.gid = atol(args[1]);
807 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200808 /* user/group name handling */
809 else if (!strcmp(args[0], "user")) {
810 struct passwd *ha_user;
811 if (global.uid != 0) {
812 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
814 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200815 }
816 errno = 0;
817 ha_user = getpwnam(args[1]);
818 if (ha_user != NULL) {
819 global.uid = (int)ha_user->pw_uid;
820 }
821 else {
822 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 +0200823 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200824 }
825 }
826 else if (!strcmp(args[0], "group")) {
827 struct group *ha_group;
828 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200829 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
831 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200832 }
833 errno = 0;
834 ha_group = getgrnam(args[1]);
835 if (ha_group != NULL) {
836 global.gid = (int)ha_group->gr_gid;
837 }
838 else {
839 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 +0200840 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200841 }
842 }
843 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.nbproc = atol(args[1]);
851 }
852 else if (!strcmp(args[0], "maxconn")) {
853 if (global.maxconn != 0) {
854 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200855 err_code |= ERR_ALERT;
856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 }
863 global.maxconn = atol(args[1]);
864#ifdef SYSTEM_MAXCONN
865 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
866 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);
867 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 }
870#endif /* SYSTEM_MAXCONN */
871 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200872 else if (!strcmp(args[0], "maxsslconn")) {
873#ifdef USE_OPENSSL
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.maxsslconn = atol(args[1]);
880#else
Emeric Brun0914df82012-10-02 18:45:42 +0200881 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200884#endif
885 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100886 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
887#ifdef USE_OPENSSL
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 free(global.listen_default_ciphers);
894 global.listen_default_ciphers = strdup(args[1]);
895#else
896 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899#endif
900 }
901 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
902#ifdef USE_OPENSSL
903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908 free(global.connect_default_ciphers);
909 global.connect_default_ciphers = strdup(args[1]);
910#else
911 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914#endif
915 }
Emeric Brun850efd52014-01-29 12:24:34 +0100916 else if (!strcmp(args[0], "ssl-server-verify")) {
917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 if (strcmp(args[1],"none") == 0)
923 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
924 else if (strcmp(args[1],"required") == 0)
925 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
926 else {
927 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200932 else if (!strcmp(args[0], "maxconnrate")) {
933 if (global.cps_lim != 0) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT;
936 goto out;
937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.cps_lim = atol(args[1]);
944 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200945 else if (!strcmp(args[0], "maxsessrate")) {
946 if (global.sps_lim != 0) {
947 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT;
949 goto out;
950 }
951 if (*(args[1]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
956 global.sps_lim = atol(args[1]);
957 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200958 else if (!strcmp(args[0], "maxsslrate")) {
959 if (global.ssl_lim != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
961 err_code |= ERR_ALERT;
962 goto out;
963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.ssl_lim = atol(args[1]);
970 }
William Lallemandd85f9172012-11-09 17:05:39 +0100971 else if (!strcmp(args[0], "maxcomprate")) {
972 if (*(args[1]) == 0) {
973 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 global.comp_rate_lim = atoi(args[1]) * 1024;
978 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100979 else if (!strcmp(args[0], "maxpipes")) {
980 if (global.maxpipes != 0) {
981 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200982 err_code |= ERR_ALERT;
983 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100984 }
985 if (*(args[1]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100989 }
990 global.maxpipes = atol(args[1]);
991 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100992 else if (!strcmp(args[0], "maxzlibmem")) {
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
William Lallemande3a7d992012-11-20 11:25:20 +0100998 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100999 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001000 else if (!strcmp(args[0], "maxcompcpuusage")) {
1001 if (*(args[1]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001007 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001008 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012}
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 else if (!strcmp(args[0], "ulimit-n")) {
1015 if (global.rlimit_nofile != 0) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT;
1018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 }
1020 if (*(args[1]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
1025 global.rlimit_nofile = atol(args[1]);
1026 }
1027 else if (!strcmp(args[0], "chroot")) {
1028 if (global.chroot != NULL) {
1029 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001030 err_code |= ERR_ALERT;
1031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 }
1033 if (*(args[1]) == 0) {
1034 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 global.chroot = strdup(args[1]);
1039 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001040 else if (!strcmp(args[0], "description")) {
1041 int i, len=0;
1042 char *d;
1043
1044 if (!*args[1]) {
1045 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1046 file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 for(i=1; *args[i]; i++)
1052 len += strlen(args[i])+1;
1053
1054 if (global.desc)
1055 free(global.desc);
1056
1057 global.desc = d = (char *)calloc(1, len);
1058
1059 d += sprintf(d, "%s", args[1]);
1060 for(i=2; *args[i]; i++)
1061 d += sprintf(d, " %s", args[i]);
1062 }
1063 else if (!strcmp(args[0], "node")) {
1064 int i;
1065 char c;
1066
1067 for (i=0; args[1][i]; i++) {
1068 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001069 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1070 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001071 break;
1072 }
1073
1074 if (!i || args[1][i]) {
1075 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1076 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1077 file, linenum, args[0]);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081
1082 if (global.node)
1083 free(global.node);
1084
1085 global.node = strdup(args[1]);
1086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 else if (!strcmp(args[0], "pidfile")) {
1088 if (global.pidfile != NULL) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
1098 global.pidfile = strdup(args[1]);
1099 }
Emeric Bruned760922010-10-22 17:59:25 +02001100 else if (!strcmp(args[0], "unix-bind")) {
1101 int cur_arg = 1;
1102 while (*(args[cur_arg])) {
1103 if (!strcmp(args[cur_arg], "prefix")) {
1104 if (global.unix_bind.prefix != NULL) {
1105 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1106 err_code |= ERR_ALERT;
1107 cur_arg += 2;
1108 continue;
1109 }
1110
1111 if (*(args[cur_arg+1]) == 0) {
1112 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1117 cur_arg += 2;
1118 continue;
1119 }
1120
1121 if (!strcmp(args[cur_arg], "mode")) {
1122
1123 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1124 cur_arg += 2;
1125 continue;
1126 }
1127
1128 if (!strcmp(args[cur_arg], "uid")) {
1129
1130 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1131 cur_arg += 2;
1132 continue;
1133 }
1134
1135 if (!strcmp(args[cur_arg], "gid")) {
1136
1137 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1138 cur_arg += 2;
1139 continue;
1140 }
1141
1142 if (!strcmp(args[cur_arg], "user")) {
1143 struct passwd *user;
1144
1145 user = getpwnam(args[cur_arg + 1]);
1146 if (!user) {
1147 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1148 file, linenum, args[0], args[cur_arg + 1 ]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152
1153 global.unix_bind.ux.uid = user->pw_uid;
1154 cur_arg += 2;
1155 continue;
1156 }
1157
1158 if (!strcmp(args[cur_arg], "group")) {
1159 struct group *group;
1160
1161 group = getgrnam(args[cur_arg + 1]);
1162 if (!group) {
1163 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1164 file, linenum, args[0], args[cur_arg + 1 ]);
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168
1169 global.unix_bind.ux.gid = group->gr_gid;
1170 cur_arg += 2;
1171 continue;
1172 }
1173
Willy Tarreaub48f9582011-09-05 01:17:06 +02001174 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001175 file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
1179 }
William Lallemand0f99e342011-10-12 17:50:54 +02001180 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1181 /* delete previous herited or defined syslog servers */
1182 struct logsrv *back;
1183 struct logsrv *tmp;
1184
1185 if (*(args[1]) != 0) {
1186 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190
1191 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1192 LIST_DEL(&tmp->list);
1193 free(tmp);
1194 }
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001197 struct sockaddr_storage *sk;
1198 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001199 struct logsrv *logsrv;
1200
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 if (*(args[1]) == 0 || *(args[2]) == 0) {
1202 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
William Lallemand0f99e342011-10-12 17:50:54 +02001206
1207 logsrv = calloc(1, sizeof(struct logsrv));
1208
1209 logsrv->facility = get_log_facility(args[2]);
1210 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001213 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
1215
William Lallemand0f99e342011-10-12 17:50:54 +02001216 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001218 logsrv->level = get_log_level(args[3]);
1219 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001221 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001222 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 }
1224 }
1225
William Lallemand0f99e342011-10-12 17:50:54 +02001226 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001227 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001228 logsrv->minlvl = get_log_level(args[4]);
1229 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001230 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001232 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001233 }
1234 }
1235
Willy Tarreau902636f2013-03-10 19:44:48 +01001236 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001237 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001238 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001239 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001240 free(logsrv);
1241 goto out;
1242 }
1243 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001244
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001245 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001246 if (port1 != port2) {
1247 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1248 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001249 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001250 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001251 goto out;
1252 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001253
William Lallemand0f99e342011-10-12 17:50:54 +02001254 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001255 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001256 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258
William Lallemand0f99e342011-10-12 17:50:54 +02001259 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001260 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001261 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1262 char *name;
1263 int len;
1264
1265 if (global.log_send_hostname != NULL) {
1266 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT;
1268 goto out;
1269 }
1270
1271 if (*(args[1]))
1272 name = args[1];
1273 else
1274 name = hostname;
1275
1276 len = strlen(name);
1277
1278 /* We'll add a space after the name to respect the log format */
1279 free(global.log_send_hostname);
1280 global.log_send_hostname = malloc(len + 2);
1281 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1282 }
Kevinm48936af2010-12-22 16:08:21 +00001283 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1284 if (*(args[1]) == 0) {
1285 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 free(global.log_tag);
1290 global.log_tag = strdup(args[1]);
1291 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001292 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1293 if (global.spread_checks != 0) {
1294 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001295 err_code |= ERR_ALERT;
1296 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001297 }
1298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001302 }
1303 global.spread_checks = atol(args[1]);
1304 if (global.spread_checks < 0 || global.spread_checks > 50) {
1305 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001306 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001309 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1310#ifdef USE_CPU_AFFINITY
1311 int cur_arg, i;
1312 unsigned int proc = 0;
1313 unsigned long cpus = 0;
1314
1315 if (strcmp(args[1], "all") == 0)
1316 proc = 0xFFFFFFFF;
1317 else if (strcmp(args[1], "odd") == 0)
1318 proc = 0x55555555;
1319 else if (strcmp(args[1], "even") == 0)
1320 proc = 0xAAAAAAAA;
1321 else {
1322 proc = atoi(args[1]);
1323 if (proc >= 1 && proc <= 32)
1324 proc = 1 << (proc - 1);
1325 }
1326
1327 if (!proc || !*args[2]) {
1328 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",
1329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
1334 cur_arg = 2;
1335 while (*args[cur_arg]) {
1336 unsigned int low, high;
1337
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001338 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001339 char *dash = strchr(args[cur_arg], '-');
1340
1341 low = high = str2uic(args[cur_arg]);
1342 if (dash)
1343 high = str2uic(dash + 1);
1344
1345 if (high < low) {
1346 unsigned int swap = low;
1347 low = high;
1348 high = swap;
1349 }
1350
1351 if (low < 0 || high >= sizeof(long) * 8) {
1352 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1353 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357
1358 while (low <= high)
1359 cpus |= 1UL << low++;
1360 }
1361 else {
1362 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1363 file, linenum, args[0], args[cur_arg]);
1364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
1366 }
1367 cur_arg++;
1368 }
1369 for (i = 0; i < 32; i++)
1370 if (proc & (1 << i))
1371 global.cpu_map[i] = cpus;
1372#else
1373 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376#endif
1377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001379 struct cfg_kw_list *kwl;
1380 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001381 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001382
1383 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1384 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1385 if (kwl->kw[index].section != CFG_GLOBAL)
1386 continue;
1387 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001388 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001389 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001390 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001392 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001393 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001394 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001395 err_code |= ERR_WARN;
1396 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001397 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001399 }
1400 }
1401 }
1402
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001404 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406
Willy Tarreau058e9072009-07-20 09:30:05 +02001407 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001408 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410}
1411
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001412void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001414 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 defproxy.mode = PR_MODE_TCP;
1416 defproxy.state = PR_STNEW;
1417 defproxy.maxconn = cfg_maxpconn;
1418 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419
Simon Horman66183002013-02-23 10:16:43 +09001420 defproxy.defsrv.check.inter = DEF_CHKINTR;
1421 defproxy.defsrv.check.fastinter = 0;
1422 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001423 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1424 defproxy.defsrv.agent.fastinter = 0;
1425 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001426 defproxy.defsrv.check.rise = DEF_RISETIME;
1427 defproxy.defsrv.check.fall = DEF_FALLTIME;
1428 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1429 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001430 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001431 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001432 defproxy.defsrv.maxqueue = 0;
1433 defproxy.defsrv.minconn = 0;
1434 defproxy.defsrv.maxconn = 0;
1435 defproxy.defsrv.slowstart = 0;
1436 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1437 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1438 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439}
1440
Willy Tarreauade5ec42010-01-28 19:33:49 +01001441
1442static int create_cond_regex_rule(const char *file, int line,
1443 struct proxy *px, int dir, int action, int flags,
1444 const char *cmd, const char *reg, const char *repl,
1445 const char **cond_start)
1446{
1447 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001448 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001449 const char *err;
1450 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001451 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001452
1453 if (px == &defproxy) {
1454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1455 err_code |= ERR_ALERT | ERR_FATAL;
1456 goto err;
1457 }
1458
1459 if (*reg == 0) {
1460 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto err;
1463 }
1464
1465 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1466 err_code |= ERR_WARN;
1467
Willy Tarreau5321c422010-01-28 20:35:13 +01001468 if (cond_start &&
1469 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001470 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1471 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1472 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto err;
1475 }
1476 }
1477 else if (cond_start && **cond_start) {
1478 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1479 file, line, cmd, *cond_start);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto err;
1482 }
1483
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001484 err_code |= warnif_cond_conflicts(cond,
1485 (dir == SMP_OPT_DIR_REQ) ?
1486 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1487 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1488 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001489
Willy Tarreauade5ec42010-01-28 19:33:49 +01001490 preg = calloc(1, sizeof(regex_t));
1491 if (!preg) {
1492 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1493 err_code = ERR_ALERT | ERR_FATAL;
1494 goto err;
1495 }
1496
1497 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1498 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1499 err_code = ERR_ALERT | ERR_FATAL;
1500 goto err;
1501 }
1502
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001503 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001504 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001505 if (repl && err) {
1506 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1507 file, line, cmd, *err);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto err;
1510 }
1511
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001512 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001513 err_code |= ERR_WARN;
1514
Willy Tarreauf4068b62012-05-08 17:37:49 +02001515 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001516 return err_code;
1517 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001518 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001519 free(preg);
1520 return err_code;
1521}
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001525 * Returns the error code, 0 if OK, or any combination of :
1526 * - ERR_ABORT: must abort ASAP
1527 * - ERR_FATAL: we can continue parsing but not start the service
1528 * - ERR_WARN: a warning has been emitted
1529 * - ERR_ALERT: an alert has been emitted
1530 * Only the two first ones can stop processing, the two others are just
1531 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001533int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1534{
1535 static struct peers *curpeers = NULL;
1536 struct peer *newpeer = NULL;
1537 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001538 struct bind_conf *bind_conf;
1539 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001540 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001541 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001542
1543 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001544 if (!*args[1]) {
1545 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001546 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001547 goto out;
1548 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 err = invalid_char(args[1]);
1551 if (err) {
1552 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1553 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001554 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001555 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001556 }
1557
1558 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1559 /*
1560 * If there are two proxies with the same name only following
1561 * combinations are allowed:
1562 */
1563 if (strcmp(curpeers->id, args[1]) == 0) {
1564 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1565 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1566 err_code |= ERR_WARN;
1567 }
1568 }
1569
1570 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1571 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1572 err_code |= ERR_ALERT | ERR_ABORT;
1573 goto out;
1574 }
1575
1576 curpeers->next = peers;
1577 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001578 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001579 curpeers->conf.line = linenum;
1580 curpeers->last_change = now.tv_sec;
1581 curpeers->id = strdup(args[1]);
1582 }
1583 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001584 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001585 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001586 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001587
1588 if (!*args[2]) {
1589 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1590 file, linenum, args[0]);
1591 err_code |= ERR_ALERT | ERR_FATAL;
1592 goto out;
1593 }
1594
1595 err = invalid_char(args[1]);
1596 if (err) {
1597 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1598 file, linenum, *err, args[1]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
1601 }
1602
1603 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1604 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1605 err_code |= ERR_ALERT | ERR_ABORT;
1606 goto out;
1607 }
1608
1609 /* the peers are linked backwards first */
1610 curpeers->count++;
1611 newpeer->next = curpeers->remote;
1612 curpeers->remote = newpeer;
1613 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001614 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001615 newpeer->conf.line = linenum;
1616
1617 newpeer->last_change = now.tv_sec;
1618 newpeer->id = strdup(args[1]);
1619
Willy Tarreau902636f2013-03-10 19:44:48 +01001620 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001621 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001622 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001625 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001626
1627 proto = protocol_by_family(sk->ss_family);
1628 if (!proto || !proto->connect) {
1629 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1630 file, linenum, args[0], args[1]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001634
1635 if (port1 != port2) {
1636 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1637 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
1640 }
1641
Willy Tarreau2aa38802013-02-20 19:20:59 +01001642 if (!port1) {
1643 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1644 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
1647 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001648
Emeric Brun32da3c42010-09-23 18:39:19 +02001649 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001650 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001651 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001652 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001653
Emeric Brun32da3c42010-09-23 18:39:19 +02001654 if (strcmp(newpeer->id, localpeer) == 0) {
1655 /* Current is local peer, it define a frontend */
1656 newpeer->local = 1;
1657
1658 if (!curpeers->peers_fe) {
1659 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1660 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1661 err_code |= ERR_ALERT | ERR_ABORT;
1662 goto out;
1663 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001664
Willy Tarreau237250c2011-07-29 01:49:03 +02001665 init_new_proxy(curpeers->peers_fe);
1666 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001667
1668 curpeers->peers_fe->last_change = now.tv_sec;
1669 curpeers->peers_fe->id = strdup(args[1]);
1670 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001671 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001672 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1673 curpeers->peers_fe->timeout.connect = 5000;
1674 curpeers->peers_fe->accept = peer_accept;
1675 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001676 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1677 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001678
1679 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1680
Willy Tarreau902636f2013-03-10 19:44:48 +01001681 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1682 if (errmsg && *errmsg) {
1683 indent_msg(&errmsg, 2);
1684 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001685 }
1686 else
1687 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1688 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001689 err_code |= ERR_FATAL;
1690 goto out;
1691 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001692
1693 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1694 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1695 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1696 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1697 l->accept = session_accept;
1698 l->handler = process_session;
1699 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1700 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1701 global.maxsock += l->maxconn;
1702 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001703 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001704 else {
1705 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1706 file, linenum, args[0], args[1],
1707 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1708 err_code |= ERR_FATAL;
1709 goto out;
1710 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 }
1712 } /* neither "peer" nor "peers" */
1713 else if (*args[0] != 0) {
1714 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
1717 }
1718
1719out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001720 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 return err_code;
1722}
1723
Simon Horman69d29f92013-02-23 15:14:19 +09001724static int init_check(struct check *check, int type, const char * file, int linenum)
1725{
1726 check->type = type;
1727
1728 /* Allocate buffer for requests... */
1729 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1730 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1731 return ERR_ALERT | ERR_ABORT;
1732 }
1733 check->bi->size = global.tune.chksize;
1734
1735 /* Allocate buffer for responses... */
1736 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1737 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1738 return ERR_ALERT | ERR_ABORT;
1739 }
1740 check->bo->size = global.tune.chksize;
1741
1742 /* Allocate buffer for partial results... */
1743 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1744 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1745 return ERR_ALERT | ERR_ABORT;
1746 }
1747
1748 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1749
1750 return 0;
1751}
Emeric Brun32da3c42010-09-23 18:39:19 +02001752
Willy Tarreau3842f002009-06-14 11:39:52 +02001753int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754{
1755 static struct proxy *curproxy = NULL;
1756 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001757 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001758 int rc;
1759 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001760 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001761 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001762 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001763 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001764 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765
Willy Tarreau977b8e42006-12-29 14:19:17 +01001766 if (!strcmp(args[0], "listen"))
1767 rc = PR_CAP_LISTEN;
1768 else if (!strcmp(args[0], "frontend"))
1769 rc = PR_CAP_FE | PR_CAP_RS;
1770 else if (!strcmp(args[0], "backend"))
1771 rc = PR_CAP_BE | PR_CAP_RS;
1772 else if (!strcmp(args[0], "ruleset"))
1773 rc = PR_CAP_RS;
1774 else
1775 rc = PR_CAP_NONE;
1776
1777 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 if (!*args[1]) {
1779 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1780 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001782 err_code |= ERR_ALERT | ERR_ABORT;
1783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001785
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001786 err = invalid_char(args[1]);
1787 if (err) {
1788 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1789 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001791 }
1792
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001793 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1794 /*
1795 * If there are two proxies with the same name only following
1796 * combinations are allowed:
1797 *
1798 * listen backend frontend ruleset
1799 * listen - - - -
1800 * backend - - OK -
1801 * frontend - OK - -
1802 * ruleset - - - -
1803 */
1804
1805 if (!strcmp(curproxy->id, args[1]) &&
1806 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1807 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001808 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1809 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1810 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001812 }
1813 }
1814
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1816 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_ALERT | ERR_ABORT;
1818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001820
Willy Tarreau97cb7802010-01-03 20:23:58 +01001821 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 curproxy->next = proxy;
1823 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001824 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1825 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001826 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001828 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829
1830 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001831 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001832 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001833
Willy Tarreau4348fad2012-09-20 16:48:07 +02001834 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1835
Willy Tarreau902636f2013-03-10 19:44:48 +01001836 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1837 if (errmsg && *errmsg) {
1838 indent_msg(&errmsg, 2);
1839 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001840 }
1841 else
1842 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1843 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_FATAL;
1845 goto out;
1846 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001847
Willy Tarreau4348fad2012-09-20 16:48:07 +02001848 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001849 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001851 }
1852
1853 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001854 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001855 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001859 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001860 curproxy->no_options = defproxy.no_options;
1861 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001862 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001863 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001864 curproxy->except_net = defproxy.except_net;
1865 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001866 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001867 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001869 if (defproxy.fwdfor_hdr_len) {
1870 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1871 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1872 }
1873
Willy Tarreaub86db342009-11-30 11:50:16 +01001874 if (defproxy.orgto_hdr_len) {
1875 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1876 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1877 }
1878
Mark Lamourinec2247f02012-01-04 13:02:01 -05001879 if (defproxy.server_id_hdr_len) {
1880 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1881 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1882 }
1883
Willy Tarreau977b8e42006-12-29 14:19:17 +01001884 if (curproxy->cap & PR_CAP_FE) {
1885 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001886 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001887 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001888
1889 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001890 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1891 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001892
1893 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 if (curproxy->cap & PR_CAP_BE) {
1897 curproxy->fullconn = defproxy.fullconn;
1898 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001900 if (defproxy.check_req) {
1901 curproxy->check_req = calloc(1, defproxy.check_len);
1902 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1903 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001906 if (defproxy.expect_str) {
1907 curproxy->expect_str = strdup(defproxy.expect_str);
1908 if (defproxy.expect_regex) {
1909 /* note: this regex is known to be valid */
1910 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1911 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1912 }
1913 }
1914
Willy Tarreau67402132012-05-31 20:40:20 +02001915 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (defproxy.cookie_name)
1917 curproxy->cookie_name = strdup(defproxy.cookie_name);
1918 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001919 if (defproxy.cookie_domain)
1920 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001921
Willy Tarreau31936852010-10-06 16:59:56 +02001922 if (defproxy.cookie_maxidle)
1923 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1924
1925 if (defproxy.cookie_maxlife)
1926 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1927
Emeric Brun647caf12009-06-30 17:57:00 +02001928 if (defproxy.rdp_cookie_name)
1929 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1930 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1931
Willy Tarreau01732802007-11-01 22:48:15 +01001932 if (defproxy.url_param_name)
1933 curproxy->url_param_name = strdup(defproxy.url_param_name);
1934 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001935
Benoitaffb4812009-03-25 13:02:10 +01001936 if (defproxy.hh_name)
1937 curproxy->hh_name = strdup(defproxy.hh_name);
1938 curproxy->hh_len = defproxy.hh_len;
1939 curproxy->hh_match_domain = defproxy.hh_match_domain;
1940
Willy Tarreauef9a3602012-12-08 22:29:20 +01001941 if (defproxy.conn_src.iface_name)
1942 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1943 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001944 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001945#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001946 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001947#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001950 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951 if (defproxy.capture_name)
1952 curproxy->capture_name = strdup(defproxy.capture_name);
1953 curproxy->capture_namelen = defproxy.capture_namelen;
1954 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001958 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001959 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001960 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001961 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001962 curproxy->uri_auth = defproxy.uri_auth;
1963 curproxy->mon_net = defproxy.mon_net;
1964 curproxy->mon_mask = defproxy.mon_mask;
1965 if (defproxy.monitor_uri)
1966 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1967 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001968 if (defproxy.defbe.name)
1969 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001970
1971 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001972 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1973 if (curproxy->conf.logformat_string &&
1974 curproxy->conf.logformat_string != default_http_log_format &&
1975 curproxy->conf.logformat_string != default_tcp_log_format &&
1976 curproxy->conf.logformat_string != clf_http_log_format)
1977 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1978
1979 if (defproxy.conf.lfs_file) {
1980 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1981 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1982 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001983 }
1984
1985 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001986 curproxy->timeout.connect = defproxy.timeout.connect;
1987 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001988 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001989 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001990 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001991 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001992 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001993 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001994 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001995 }
1996
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001998
1999 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002000 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002001 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002002 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002003 LIST_INIT(&node->list);
2004 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2005 }
2006
Willy Tarreau62a61232013-04-12 18:13:46 +02002007 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2008 if (curproxy->conf.uniqueid_format_string)
2009 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2010
2011 if (defproxy.conf.uif_file) {
2012 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2013 curproxy->conf.uif_line = defproxy.conf.uif_line;
2014 }
William Lallemanda73203e2012-03-12 12:48:57 +01002015
2016 /* copy default header unique id */
2017 if (defproxy.header_unique_id)
2018 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2019
William Lallemand82fe75c2012-10-23 10:25:10 +02002020 /* default compression options */
2021 if (defproxy.comp != NULL) {
2022 curproxy->comp = calloc(1, sizeof(struct comp));
2023 curproxy->comp->algos = defproxy.comp->algos;
2024 curproxy->comp->types = defproxy.comp->types;
2025 }
2026
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002028 curproxy->conf.used_listener_id = EB_ROOT;
2029 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002030
Willy Tarreau93893792009-07-23 13:19:11 +02002031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032 }
2033 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2034 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002035 /* FIXME-20070101: we should do this too at the end of the
2036 * config parsing to free all default values.
2037 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002038 free(defproxy.check_req);
2039 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002040 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002041 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002042 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002043 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002044 free(defproxy.capture_name);
2045 free(defproxy.monitor_uri);
2046 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002047 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002048 free(defproxy.fwdfor_hdr_name);
2049 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002050 free(defproxy.orgto_hdr_name);
2051 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002052 free(defproxy.server_id_hdr_name);
2053 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002054 free(defproxy.expect_str);
2055 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002056
Willy Tarreau62a61232013-04-12 18:13:46 +02002057 if (defproxy.conf.logformat_string != default_http_log_format &&
2058 defproxy.conf.logformat_string != default_tcp_log_format &&
2059 defproxy.conf.logformat_string != clf_http_log_format)
2060 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002061
Willy Tarreau62a61232013-04-12 18:13:46 +02002062 free(defproxy.conf.uniqueid_format_string);
2063 free(defproxy.conf.lfs_file);
2064 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002065
Willy Tarreaua534fea2008-08-03 12:19:50 +02002066 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002067 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002068
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 /* we cannot free uri_auth because it might already be used */
2070 init_default_instance();
2071 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002072 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2073 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 }
2077 else if (curproxy == NULL) {
2078 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002082
2083 /* update the current file and line being parsed */
2084 curproxy->conf.args.file = curproxy->conf.file;
2085 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086
2087 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002089 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002090 int cur_arg;
2091
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 if (curproxy == &defproxy) {
2093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002097 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099
Willy Tarreau24709282013-03-10 21:32:12 +01002100 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002101 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002106
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002107 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002108
2109 /* use default settings for unix sockets */
2110 bind_conf->ux.uid = global.unix_bind.ux.uid;
2111 bind_conf->ux.gid = global.unix_bind.ux.gid;
2112 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002113
2114 /* NOTE: the following line might create several listeners if there
2115 * are comma-separated IPs or port ranges. So all further processing
2116 * will have to be applied to all listeners created after last_listen.
2117 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002118 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2119 if (errmsg && *errmsg) {
2120 indent_msg(&errmsg, 2);
2121 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002122 }
2123 else
2124 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2125 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
2128 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002129
Willy Tarreau4348fad2012-09-20 16:48:07 +02002130 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2131 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002132 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002133 }
2134
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002135 cur_arg = 2;
2136 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002137 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002138 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002139 char *err;
2140
Willy Tarreau26982662012-09-12 23:17:10 +02002141 kw = bind_find_kw(args[cur_arg]);
2142 if (kw) {
2143 char *err = NULL;
2144 int code;
2145
2146 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002147 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2148 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002149 cur_arg += 1 + kw->skip ;
2150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
2152 }
2153
Willy Tarreau4348fad2012-09-20 16:48:07 +02002154 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002155 err_code |= code;
2156
2157 if (code) {
2158 if (err && *err) {
2159 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002160 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002161 }
2162 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002163 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2164 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002165 if (code & ERR_FATAL) {
2166 free(err);
2167 cur_arg += 1 + kw->skip;
2168 goto out;
2169 }
2170 }
2171 free(err);
2172 cur_arg += 1 + kw->skip;
2173 continue;
2174 }
2175
Willy Tarreau8638f482012-09-18 18:01:17 +02002176 err = NULL;
2177 if (!bind_dumped) {
2178 bind_dump_kws(&err);
2179 indent_msg(&err, 4);
2180 bind_dumped = 1;
2181 }
2182
2183 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2184 file, linenum, args[0], args[1], args[cur_arg],
2185 err ? " Registered keywords :" : "", err ? err : "");
2186 free(err);
2187
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002190 }
Willy Tarreau93893792009-07-23 13:19:11 +02002191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
2193 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2194 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2195 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002200 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 /* flush useless bits */
2204 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002207 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002210
Willy Tarreau1c47f852006-07-09 08:22:27 +02002211 if (!*args[1]) {
2212 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002216 }
2217
Willy Tarreaua534fea2008-08-03 12:19:50 +02002218 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002219 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002220 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002221 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002222 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2223
Willy Tarreau93893792009-07-23 13:19:11 +02002224 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2227 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2228 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2229 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2230 else {
2231 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
2235 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002236 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002237 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002238
2239 if (curproxy == &defproxy) {
2240 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2241 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002244 }
2245
2246 if (!*args[1]) {
2247 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002251 }
2252
2253 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002254 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002255
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002256 if (curproxy->uuid <= 0) {
2257 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002261 }
2262
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002263 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2264 if (node) {
2265 struct proxy *target = container_of(node, struct proxy, conf.id);
2266 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2267 file, linenum, proxy_type_str(curproxy), curproxy->id,
2268 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002273 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002274 else if (!strcmp(args[0], "description")) {
2275 int i, len=0;
2276 char *d;
2277
Cyril Bonté99ed3272010-01-24 23:29:44 +01002278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2280 file, linenum, args[0]);
2281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
2283 }
2284
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002285 if (!*args[1]) {
2286 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2287 file, linenum, args[0]);
2288 return -1;
2289 }
2290
2291 for(i=1; *args[i]; i++)
2292 len += strlen(args[i])+1;
2293
2294 d = (char *)calloc(1, len);
2295 curproxy->desc = d;
2296
2297 d += sprintf(d, "%s", args[1]);
2298 for(i=2; *args[i]; i++)
2299 d += sprintf(d, " %s", args[i]);
2300
2301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2303 curproxy->state = PR_STSTOPPED;
2304 }
2305 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2306 curproxy->state = PR_STNEW;
2307 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002308 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2309 int cur_arg = 1;
2310 unsigned int set = 0;
2311
2312 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002313 unsigned int low, high;
2314
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002315 if (strcmp(args[cur_arg], "all") == 0) {
2316 set = 0;
2317 break;
2318 }
2319 else if (strcmp(args[cur_arg], "odd") == 0) {
2320 set |= 0x55555555;
2321 }
2322 else if (strcmp(args[cur_arg], "even") == 0) {
2323 set |= 0xAAAAAAAA;
2324 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002325 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002326 char *dash = strchr(args[cur_arg], '-');
2327
2328 low = high = str2uic(args[cur_arg]);
2329 if (dash)
2330 high = str2uic(dash + 1);
2331
2332 if (high < low) {
2333 unsigned int swap = low;
2334 low = high;
2335 high = swap;
2336 }
2337
2338 if (low < 1 || high > 32) {
2339 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002343 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002344
2345 if (high > global.nbproc) {
2346 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2347 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002349 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002350 while (low <= high)
2351 set |= 1 << (low++ - 1);
2352 }
2353 else {
2354 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2355 file, linenum, args[0]);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002358 }
2359 cur_arg++;
2360 }
2361 curproxy->bind_proc = set;
2362 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002363 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002364 if (curproxy == &defproxy) {
2365 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002368 }
2369
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002370 err = invalid_char(args[1]);
2371 if (err) {
2372 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2373 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002375 }
2376
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002377 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002378 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2379 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002382 }
2383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2385 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386
Willy Tarreau977b8e42006-12-29 14:19:17 +01002387 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 if (*(args[1]) == 0) {
2391 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002396
Willy Tarreau67402132012-05-31 20:40:20 +02002397 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002398 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002399 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002400 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 curproxy->cookie_name = strdup(args[1]);
2402 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002403
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 cur_arg = 2;
2405 while (*(args[cur_arg])) {
2406 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002407 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }
2409 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002410 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002413 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 }
2415 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002416 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 }
2418 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002419 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002421 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002422 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002425 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002427 else if (!strcmp(args[cur_arg], "httponly")) {
2428 curproxy->ck_opts |= PR_CK_HTTPONLY;
2429 }
2430 else if (!strcmp(args[cur_arg], "secure")) {
2431 curproxy->ck_opts |= PR_CK_SECURE;
2432 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002433 else if (!strcmp(args[cur_arg], "domain")) {
2434 if (!*args[cur_arg + 1]) {
2435 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2436 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002439 }
2440
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002441 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002442 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002443 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2444 " dots nor does not start with a dot."
2445 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002446 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002447 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002448 }
2449
2450 err = invalid_domainchar(args[cur_arg + 1]);
2451 if (err) {
2452 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2453 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002456 }
2457
Willy Tarreau68a897b2009-12-03 23:28:34 +01002458 if (!curproxy->cookie_domain) {
2459 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2460 } else {
2461 /* one domain was already specified, add another one by
2462 * building the string which will be returned along with
2463 * the cookie.
2464 */
2465 char *new_ptr;
2466 int new_len = strlen(curproxy->cookie_domain) +
2467 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2468 new_ptr = malloc(new_len);
2469 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2470 free(curproxy->cookie_domain);
2471 curproxy->cookie_domain = new_ptr;
2472 }
Willy Tarreau31936852010-10-06 16:59:56 +02002473 cur_arg++;
2474 }
2475 else if (!strcmp(args[cur_arg], "maxidle")) {
2476 unsigned int maxidle;
2477 const char *res;
2478
2479 if (!*args[cur_arg + 1]) {
2480 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2481 file, linenum, args[cur_arg]);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2487 if (res) {
2488 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2489 file, linenum, *res, args[cur_arg]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493 curproxy->cookie_maxidle = maxidle;
2494 cur_arg++;
2495 }
2496 else if (!strcmp(args[cur_arg], "maxlife")) {
2497 unsigned int maxlife;
2498 const char *res;
2499
2500 if (!*args[cur_arg + 1]) {
2501 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2502 file, linenum, args[cur_arg]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506
2507 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2508 if (res) {
2509 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2510 file, linenum, *res, args[cur_arg]);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002515 cur_arg++;
2516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002518 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 +02002519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 }
2523 cur_arg++;
2524 }
Willy Tarreau67402132012-05-31 20:40:20 +02002525 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 }
2530
Willy Tarreau67402132012-05-31 20:40:20 +02002531 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2533 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002536
Willy Tarreau67402132012-05-31 20:40:20 +02002537 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002538 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2539 file, linenum);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002543 else if (!strcmp(args[0], "persist")) { /* persist */
2544 if (*(args[1]) == 0) {
2545 Alert("parsing [%s:%d] : missing persist method.\n",
2546 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002549 }
2550
2551 if (!strncmp(args[1], "rdp-cookie", 10)) {
2552 curproxy->options2 |= PR_O2_RDPC_PRST;
2553
Emeric Brunb982a3d2010-01-04 15:45:53 +01002554 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002555 const char *beg, *end;
2556
2557 beg = args[1] + 11;
2558 end = strchr(beg, ')');
2559
2560 if (!end || end == beg) {
2561 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2562 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002565 }
2566
2567 free(curproxy->rdp_cookie_name);
2568 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2569 curproxy->rdp_cookie_len = end-beg;
2570 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002571 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002572 free(curproxy->rdp_cookie_name);
2573 curproxy->rdp_cookie_name = strdup("msts");
2574 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2575 }
2576 else { /* syntax */
2577 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2578 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
2580 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002581 }
2582 }
2583 else {
2584 Alert("parsing [%s:%d] : unknown persist method.\n",
2585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002588 }
2589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002591 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002593 if (curproxy == &defproxy) {
2594 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
Willy Tarreau977b8e42006-12-29 14:19:17 +01002599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002603 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 }
2608 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002609 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 curproxy->appsession_name = strdup(args[1]);
2611 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2612 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002613 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2614 if (err) {
2615 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2616 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002619 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002620 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002621
Willy Tarreau51041c72007-09-09 21:56:53 +02002622 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2623 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_ABORT;
2625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002627
2628 cur_arg = 6;
2629 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002630 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2631 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002632 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002633 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002634 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002635 } else if (!strcmp(args[cur_arg], "prefix")) {
2636 curproxy->options2 |= PR_O2_AS_PFX;
2637 } else if (!strcmp(args[cur_arg], "mode")) {
2638 if (!*args[cur_arg + 1]) {
2639 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2640 file, linenum, args[0], args[cur_arg]);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644
2645 cur_arg++;
2646 if (!strcmp(args[cur_arg], "query-string")) {
2647 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2648 curproxy->options2 |= PR_O2_AS_M_QS;
2649 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2650 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2651 curproxy->options2 |= PR_O2_AS_M_PP;
2652 } else {
2653 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002658 cur_arg++;
2659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 } /* Url App Session */
2661 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002664
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002666 if (curproxy == &defproxy) {
2667 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 if (*(args[4]) == 0) {
2673 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002678 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 curproxy->capture_name = strdup(args[2]);
2680 curproxy->capture_namelen = strlen(curproxy->capture_name);
2681 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 curproxy->to_log |= LW_COOKIE;
2683 }
2684 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2685 struct cap_hdr *hdr;
2686
2687 if (curproxy == &defproxy) {
2688 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 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692
2693 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2694 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2695 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
2699
2700 hdr = calloc(sizeof(struct cap_hdr), 1);
2701 hdr->next = curproxy->req_cap;
2702 hdr->name = strdup(args[3]);
2703 hdr->namelen = strlen(args[3]);
2704 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002705 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 hdr->index = curproxy->nb_req_cap++;
2707 curproxy->req_cap = hdr;
2708 curproxy->to_log |= LW_REQHDR;
2709 }
2710 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2711 struct cap_hdr *hdr;
2712
2713 if (curproxy == &defproxy) {
2714 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 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 }
2718
2719 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2720 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2721 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 }
2725 hdr = calloc(sizeof(struct cap_hdr), 1);
2726 hdr->next = curproxy->rsp_cap;
2727 hdr->name = strdup(args[3]);
2728 hdr->namelen = strlen(args[3]);
2729 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002730 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 hdr->index = curproxy->nb_rsp_cap++;
2732 curproxy->rsp_cap = hdr;
2733 curproxy->to_log |= LW_RSPHDR;
2734 }
2735 else {
2736 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 }
2741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 if (*(args[1]) == 0) {
2747 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 }
2752 curproxy->conn_retries = atol(args[1]);
2753 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002754 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002755 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002756
2757 if (curproxy == &defproxy) {
2758 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762
Willy Tarreau20b0de52012-12-24 15:45:22 +01002763 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2764 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2765 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2766 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002767 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002768 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2769 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 +01002770 file, linenum, args[0]);
2771 err_code |= ERR_WARN;
2772 }
2773
Willy Tarreauff011f22011-01-06 17:51:27 +01002774 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002775
Willy Tarreauff011f22011-01-06 17:51:27 +01002776 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002777 err_code |= ERR_ALERT | ERR_ABORT;
2778 goto out;
2779 }
2780
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002781 err_code |= warnif_cond_conflicts(rule->cond,
2782 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2783 file, linenum);
2784
Willy Tarreauff011f22011-01-06 17:51:27 +01002785 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002786 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002787 else if (!strcmp(args[0], "http-response")) { /* response access control */
2788 struct http_res_rule *rule;
2789
2790 if (curproxy == &defproxy) {
2791 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
2794 }
2795
2796 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2797 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2798 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2799 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2800 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2801 file, linenum, args[0]);
2802 err_code |= ERR_WARN;
2803 }
2804
2805 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2806
2807 if (!rule) {
2808 err_code |= ERR_ALERT | ERR_ABORT;
2809 goto out;
2810 }
2811
2812 err_code |= warnif_cond_conflicts(rule->cond,
2813 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2814 file, linenum);
2815
2816 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2817 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002818 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2819 /* set the header name and length into the proxy structure */
2820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2821 err_code |= ERR_WARN;
2822
2823 if (!*args[1]) {
2824 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2825 file, linenum, args[0]);
2826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
2828 }
2829
2830 /* set the desired header name */
2831 free(curproxy->server_id_hdr_name);
2832 curproxy->server_id_hdr_name = strdup(args[1]);
2833 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2834 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002835 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002836 if (curproxy == &defproxy) {
2837 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002840 }
2841
Willy Tarreauef6494c2010-01-28 17:12:36 +01002842 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002843 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2844 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002847 }
2848
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002849 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2850 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2851 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002854 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002855
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002856 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002857 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002858 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002859 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002860 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002861
Cyril Bonté99ed3272010-01-24 23:29:44 +01002862 if (curproxy == &defproxy) {
2863 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002868 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002869 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2870 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002873 }
2874
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002875 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002876 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002877 err_code |= warnif_cond_conflicts(rule->cond,
2878 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2879 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002880 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002881 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002882 struct switching_rule *rule;
2883
Willy Tarreaub099aca2008-10-12 17:26:37 +02002884 if (curproxy == &defproxy) {
2885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002888 }
2889
Willy Tarreau55ea7572007-06-17 19:56:27 +02002890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002892
2893 if (*(args[1]) == 0) {
2894 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002897 }
2898
Willy Tarreauef6494c2010-01-28 17:12:36 +01002899 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002900 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002904 }
2905
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002906 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2907 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2908 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002911 }
2912
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002913 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002914
Willy Tarreau55ea7572007-06-17 19:56:27 +02002915 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2916 rule->cond = cond;
2917 rule->be.name = strdup(args[1]);
2918 LIST_INIT(&rule->list);
2919 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2920 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002921 else if (strcmp(args[0], "use-server") == 0) {
2922 struct server_rule *rule;
2923
2924 if (curproxy == &defproxy) {
2925 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
2929
2930 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2931 err_code |= ERR_WARN;
2932
2933 if (*(args[1]) == 0) {
2934 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2940 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2941 file, linenum, args[0]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002946 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2947 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2948 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002953 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002954
2955 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2956 rule->cond = cond;
2957 rule->srv.name = strdup(args[1]);
2958 LIST_INIT(&rule->list);
2959 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2960 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2961 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002962 else if ((!strcmp(args[0], "force-persist")) ||
2963 (!strcmp(args[0], "ignore-persist"))) {
2964 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002965
2966 if (curproxy == &defproxy) {
2967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
2972 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2973 err_code |= ERR_WARN;
2974
Willy Tarreauef6494c2010-01-28 17:12:36 +01002975 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002976 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2977 file, linenum, args[0]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002982 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2983 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2984 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002989 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2990 * where force-persist is applied.
2991 */
2992 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002993
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002994 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002995 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002996 if (!strcmp(args[0], "force-persist")) {
2997 rule->type = PERSIST_TYPE_FORCE;
2998 } else {
2999 rule->type = PERSIST_TYPE_IGNORE;
3000 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003001 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003002 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003003 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 else if (!strcmp(args[0], "stick-table")) {
3005 int myidx = 1;
3006
Emeric Brun32da3c42010-09-23 18:39:19 +02003007 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003008 curproxy->table.type = (unsigned int)-1;
3009 while (*args[myidx]) {
3010 const char *err;
3011
3012 if (strcmp(args[myidx], "size") == 0) {
3013 myidx++;
3014 if (!*(args[myidx])) {
3015 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3016 file, linenum, args[myidx-1]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3021 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3022 file, linenum, *err, args[myidx-1]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003026 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003028 else if (strcmp(args[myidx], "peers") == 0) {
3029 myidx++;
Godbach50523162013-12-11 19:48:57 +08003030 if (!*(args[myidx])) {
3031 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3032 file, linenum, args[myidx-1]);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003036 curproxy->table.peers.name = strdup(args[myidx++]);
3037 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 else if (strcmp(args[myidx], "expire") == 0) {
3039 myidx++;
3040 if (!*(args[myidx])) {
3041 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3042 file, linenum, args[myidx-1]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3047 if (err) {
3048 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3049 file, linenum, *err, args[myidx-1]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003054 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003055 }
3056 else if (strcmp(args[myidx], "nopurge") == 0) {
3057 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003058 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 }
3060 else if (strcmp(args[myidx], "type") == 0) {
3061 myidx++;
3062 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3063 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3064 file, linenum, args[myidx]);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003068 /* myidx already points to next arg */
3069 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003070 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003071 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003072 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003073
3074 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003075 nw = args[myidx];
3076 while (*nw) {
3077 /* the "store" keyword supports a comma-separated list */
3078 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003079 sa = NULL; /* store arg */
3080 while (*nw && *nw != ',') {
3081 if (*nw == '(') {
3082 *nw = 0;
3083 sa = ++nw;
3084 while (*nw != ')') {
3085 if (!*nw) {
3086 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3087 file, linenum, args[0], cw);
3088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
3090 }
3091 nw++;
3092 }
3093 *nw = '\0';
3094 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003095 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003096 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003097 if (*nw)
3098 *nw++ = '\0';
3099 type = stktable_get_data_type(cw);
3100 if (type < 0) {
3101 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3102 file, linenum, args[0], cw);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
Willy Tarreauac782882010-06-20 10:41:54 +02003106
3107 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3108 switch (err) {
3109 case PE_NONE: break;
3110 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003111 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3112 file, linenum, args[0], cw);
3113 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003114 break;
3115
3116 case PE_ARG_MISSING:
3117 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3118 file, linenum, args[0], cw);
3119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121
3122 case PE_ARG_NOT_USED:
3123 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3124 file, linenum, args[0], cw);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127
3128 default:
3129 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3130 file, linenum, args[0], cw);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003133 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003134 }
3135 myidx++;
3136 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003137 else {
3138 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3139 file, linenum, args[myidx]);
3140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003142 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003143 }
3144
3145 if (!curproxy->table.size) {
3146 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3147 file, linenum);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151
3152 if (curproxy->table.type == (unsigned int)-1) {
3153 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3154 file, linenum);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158 }
3159 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003160 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003161 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 int myidx = 0;
3163 const char *name = NULL;
3164 int flags;
3165
3166 if (curproxy == &defproxy) {
3167 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171
3172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3173 err_code |= ERR_WARN;
3174 goto out;
3175 }
3176
3177 myidx++;
3178 if ((strcmp(args[myidx], "store") == 0) ||
3179 (strcmp(args[myidx], "store-request") == 0)) {
3180 myidx++;
3181 flags = STK_IS_STORE;
3182 }
3183 else if (strcmp(args[myidx], "store-response") == 0) {
3184 myidx++;
3185 flags = STK_IS_STORE | STK_ON_RSP;
3186 }
3187 else if (strcmp(args[myidx], "match") == 0) {
3188 myidx++;
3189 flags = STK_IS_MATCH;
3190 }
3191 else if (strcmp(args[myidx], "on") == 0) {
3192 myidx++;
3193 flags = STK_IS_MATCH | STK_IS_STORE;
3194 }
3195 else {
3196 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
3199 }
3200
3201 if (*(args[myidx]) == 0) {
3202 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003207 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003208 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003209 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003210 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214
3215 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003216 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3217 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3218 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003219 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003220 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003221 goto out;
3222 }
3223 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003224 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3225 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3226 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003227 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003228 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003229 goto out;
3230 }
3231 }
3232
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003233 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003234 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003235
Emeric Brunb982a3d2010-01-04 15:45:53 +01003236 if (strcmp(args[myidx], "table") == 0) {
3237 myidx++;
3238 name = args[myidx++];
3239 }
3240
Willy Tarreauef6494c2010-01-28 17:12:36 +01003241 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003242 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3243 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3244 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003245 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003246 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003247 goto out;
3248 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003250 else if (*(args[myidx])) {
3251 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3252 file, linenum, args[0], args[myidx]);
3253 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003254 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003255 goto out;
3256 }
Emeric Brun97679e72010-09-23 17:56:44 +02003257 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003258 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003259 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003260 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003261
Emeric Brunb982a3d2010-01-04 15:45:53 +01003262 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3263 rule->cond = cond;
3264 rule->expr = expr;
3265 rule->flags = flags;
3266 rule->table.name = name ? strdup(name) : NULL;
3267 LIST_INIT(&rule->list);
3268 if (flags & STK_ON_RSP)
3269 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3270 else
3271 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003276
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3278 curproxy->uri_auth = NULL; /* we must detach from the default config */
3279
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003280 if (!*args[1]) {
3281 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003282 } else if (!strcmp(args[1], "admin")) {
3283 struct stats_admin_rule *rule;
3284
3285 if (curproxy == &defproxy) {
3286 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
3289 }
3290
3291 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3292 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3293 err_code |= ERR_ALERT | ERR_ABORT;
3294 goto out;
3295 }
3296
3297 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3298 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3299 file, linenum, args[0], args[1]);
3300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
3302 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003303 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3304 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3305 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
3308 }
3309
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003310 err_code |= warnif_cond_conflicts(cond,
3311 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3312 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003313
3314 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3315 rule->cond = cond;
3316 LIST_INIT(&rule->list);
3317 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 } else if (!strcmp(args[1], "uri")) {
3319 if (*(args[2]) == 0) {
3320 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3324 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_ABORT;
3326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328 } else if (!strcmp(args[1], "realm")) {
3329 if (*(args[2]) == 0) {
3330 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3334 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_ABORT;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003338 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003339 unsigned interval;
3340
3341 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3342 if (err) {
3343 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3344 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003347 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3348 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_ABORT;
3350 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003351 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003352 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003353 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003354
3355 if (curproxy == &defproxy) {
3356 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360
3361 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3362 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3363 err_code |= ERR_ALERT | ERR_ABORT;
3364 goto out;
3365 }
3366
Willy Tarreauff011f22011-01-06 17:51:27 +01003367 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3368 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003369 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3370 file, linenum, args[0]);
3371 err_code |= ERR_WARN;
3372 }
3373
Willy Tarreauff011f22011-01-06 17:51:27 +01003374 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003375
Willy Tarreauff011f22011-01-06 17:51:27 +01003376 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003377 err_code |= ERR_ALERT | ERR_ABORT;
3378 goto out;
3379 }
3380
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003381 err_code |= warnif_cond_conflicts(rule->cond,
3382 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3383 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003384 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003385
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 } else if (!strcmp(args[1], "auth")) {
3387 if (*(args[2]) == 0) {
3388 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3392 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_ABORT;
3394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 }
3396 } else if (!strcmp(args[1], "scope")) {
3397 if (*(args[2]) == 0) {
3398 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3402 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_ABORT;
3404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406 } else if (!strcmp(args[1], "enable")) {
3407 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_ALERT | ERR_ABORT;
3410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003412 } else if (!strcmp(args[1], "hide-version")) {
3413 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3414 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_ABORT;
3416 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003417 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003418 } else if (!strcmp(args[1], "show-legends")) {
3419 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3420 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3421 err_code |= ERR_ALERT | ERR_ABORT;
3422 goto out;
3423 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003424 } else if (!strcmp(args[1], "show-node")) {
3425
3426 if (*args[2]) {
3427 int i;
3428 char c;
3429
3430 for (i=0; args[2][i]; i++) {
3431 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003432 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3433 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003434 break;
3435 }
3436
3437 if (!i || args[2][i]) {
3438 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3439 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3440 file, linenum, args[0], args[1]);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444 }
3445
3446 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3447 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3448 err_code |= ERR_ALERT | ERR_ABORT;
3449 goto out;
3450 }
3451 } else if (!strcmp(args[1], "show-desc")) {
3452 char *desc = NULL;
3453
3454 if (*args[2]) {
3455 int i, len=0;
3456 char *d;
3457
3458 for(i=2; *args[i]; i++)
3459 len += strlen(args[i])+1;
3460
3461 desc = d = (char *)calloc(1, len);
3462
3463 d += sprintf(d, "%s", args[2]);
3464 for(i=3; *args[i]; i++)
3465 d += sprintf(d, " %s", args[i]);
3466 }
3467
3468 if (!*args[2] && !global.desc)
3469 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3470 file, linenum, args[1]);
3471 else {
3472 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3473 free(desc);
3474 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3475 err_code |= ERR_ALERT | ERR_ABORT;
3476 goto out;
3477 }
3478 free(desc);
3479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003481stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003482 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 +01003483 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
3487 }
3488 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003489 int optnum;
3490
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003491 if (*(args[1]) == '\0') {
3492 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3493 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003497
3498 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3499 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003500 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3501 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3502 file, linenum, cfg_opts[optnum].name);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
Willy Tarreau93893792009-07-23 13:19:11 +02003506 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3507 err_code |= ERR_WARN;
3508 goto out;
3509 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003510
Willy Tarreau3842f002009-06-14 11:39:52 +02003511 curproxy->no_options &= ~cfg_opts[optnum].val;
3512 curproxy->options &= ~cfg_opts[optnum].val;
3513
3514 switch (kwm) {
3515 case KWM_STD:
3516 curproxy->options |= cfg_opts[optnum].val;
3517 break;
3518 case KWM_NO:
3519 curproxy->no_options |= cfg_opts[optnum].val;
3520 break;
3521 case KWM_DEF: /* already cleared */
3522 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003523 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003524
Willy Tarreau93893792009-07-23 13:19:11 +02003525 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003526 }
3527 }
3528
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003529 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3530 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003531 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3532 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3533 file, linenum, cfg_opts2[optnum].name);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
Willy Tarreau93893792009-07-23 13:19:11 +02003537 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3538 err_code |= ERR_WARN;
3539 goto out;
3540 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003541
Willy Tarreau3842f002009-06-14 11:39:52 +02003542 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3543 curproxy->options2 &= ~cfg_opts2[optnum].val;
3544
3545 switch (kwm) {
3546 case KWM_STD:
3547 curproxy->options2 |= cfg_opts2[optnum].val;
3548 break;
3549 case KWM_NO:
3550 curproxy->no_options2 |= cfg_opts2[optnum].val;
3551 break;
3552 case KWM_DEF: /* already cleared */
3553 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003554 }
Willy Tarreau93893792009-07-23 13:19:11 +02003555 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003556 }
3557 }
3558
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003559 /* HTTP options override each other. They can be cancelled using
3560 * "no option xxx" which only switches to default mode if the mode
3561 * was this one (useful for cancelling options set in defaults
3562 * sections).
3563 */
3564 if (strcmp(args[1], "httpclose") == 0) {
3565 if (kwm == KWM_STD) {
3566 curproxy->options &= ~PR_O_HTTP_MODE;
3567 curproxy->options |= PR_O_HTTP_PCL;
3568 goto out;
3569 }
3570 else if (kwm == KWM_NO) {
3571 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3572 curproxy->options &= ~PR_O_HTTP_MODE;
3573 goto out;
3574 }
3575 }
3576 else if (strcmp(args[1], "forceclose") == 0) {
3577 if (kwm == KWM_STD) {
3578 curproxy->options &= ~PR_O_HTTP_MODE;
3579 curproxy->options |= PR_O_HTTP_FCL;
3580 goto out;
3581 }
3582 else if (kwm == KWM_NO) {
3583 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3584 curproxy->options &= ~PR_O_HTTP_MODE;
3585 goto out;
3586 }
3587 }
3588 else if (strcmp(args[1], "http-server-close") == 0) {
3589 if (kwm == KWM_STD) {
3590 curproxy->options &= ~PR_O_HTTP_MODE;
3591 curproxy->options |= PR_O_HTTP_SCL;
3592 goto out;
3593 }
3594 else if (kwm == KWM_NO) {
3595 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3596 curproxy->options &= ~PR_O_HTTP_MODE;
3597 goto out;
3598 }
3599 }
3600 else if (strcmp(args[1], "http-keep-alive") == 0) {
3601 if (kwm == KWM_STD) {
3602 curproxy->options &= ~PR_O_HTTP_MODE;
3603 curproxy->options |= PR_O_HTTP_KAL;
3604 goto out;
3605 }
3606 else if (kwm == KWM_NO) {
3607 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3608 curproxy->options &= ~PR_O_HTTP_MODE;
3609 goto out;
3610 }
3611 }
3612 else if (strcmp(args[1], "http-tunnel") == 0) {
3613 if (kwm == KWM_STD) {
3614 curproxy->options &= ~PR_O_HTTP_MODE;
3615 curproxy->options |= PR_O_HTTP_TUN;
3616 goto out;
3617 }
3618 else if (kwm == KWM_NO) {
3619 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3620 curproxy->options &= ~PR_O_HTTP_MODE;
3621 goto out;
3622 }
3623 }
3624
Willy Tarreau3842f002009-06-14 11:39:52 +02003625 if (kwm != KWM_STD) {
3626 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003627 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003630 }
3631
Emeric Brun3a058f32009-06-30 18:26:00 +02003632 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003633 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003635 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003636 if (*(args[2]) != '\0') {
3637 if (!strcmp(args[2], "clf")) {
3638 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003639 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003640 } else {
3641 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003644 }
3645 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003646 if (curproxy->conf.logformat_string != default_http_log_format &&
3647 curproxy->conf.logformat_string != default_tcp_log_format &&
3648 curproxy->conf.logformat_string != clf_http_log_format)
3649 free(curproxy->conf.logformat_string);
3650 curproxy->conf.logformat_string = logformat;
3651
3652 free(curproxy->conf.lfs_file);
3653 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3654 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003655 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003656 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003658 if (curproxy->conf.logformat_string != default_http_log_format &&
3659 curproxy->conf.logformat_string != default_tcp_log_format &&
3660 curproxy->conf.logformat_string != clf_http_log_format)
3661 free(curproxy->conf.logformat_string);
3662 curproxy->conf.logformat_string = default_tcp_log_format;
3663
3664 free(curproxy->conf.lfs_file);
3665 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3666 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 else if (!strcmp(args[1], "tcpka")) {
3669 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003670 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003672
3673 if (curproxy->cap & PR_CAP_FE)
3674 curproxy->options |= PR_O_TCP_CLI_KA;
3675 if (curproxy->cap & PR_CAP_BE)
3676 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 }
3678 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003679 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_WARN;
3681
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003683 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003684 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003685 curproxy->options2 &= ~PR_O2_CHK_ANY;
3686 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 if (!*args[2]) { /* no argument */
3688 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3689 curproxy->check_len = strlen(DEF_CHECK_REQ);
3690 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003691 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 curproxy->check_req = (char *)malloc(reqlen);
3693 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003694 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003696 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 if (*args[4])
3698 reqlen += strlen(args[4]);
3699 else
3700 reqlen += strlen("HTTP/1.0");
3701
3702 curproxy->check_req = (char *)malloc(reqlen);
3703 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003704 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003706 }
3707 else if (!strcmp(args[1], "ssl-hello-chk")) {
3708 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003711
Willy Tarreaua534fea2008-08-03 12:19:50 +02003712 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003713 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003714 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003715 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
Willy Tarreau23677902007-05-08 23:50:35 +02003717 else if (!strcmp(args[1], "smtpchk")) {
3718 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003719 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003720 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003721 curproxy->options2 &= ~PR_O2_CHK_ANY;
3722 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003723
3724 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3725 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3726 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3727 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3728 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3729 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3730 curproxy->check_req = (char *)malloc(reqlen);
3731 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3732 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3733 } else {
3734 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3735 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3736 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3737 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3738 }
3739 }
3740 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003741 else if (!strcmp(args[1], "pgsql-check")) {
3742 /* use PostgreSQL request to check servers' health */
3743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3744 err_code |= ERR_WARN;
3745
3746 free(curproxy->check_req);
3747 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003748 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003749 curproxy->options2 |= PR_O2_PGSQL_CHK;
3750
3751 if (*(args[2])) {
3752 int cur_arg = 2;
3753
3754 while (*(args[cur_arg])) {
3755 if (strcmp(args[cur_arg], "user") == 0) {
3756 char * packet;
3757 uint32_t packet_len;
3758 uint32_t pv;
3759
3760 /* suboption header - needs additional argument for it */
3761 if (*(args[cur_arg+1]) == 0) {
3762 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3763 file, linenum, args[0], args[1], args[cur_arg]);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
3767
3768 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3769 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3770 pv = htonl(0x30000); /* protocol version 3.0 */
3771
3772 packet = (char*) calloc(1, packet_len);
3773
3774 memcpy(packet + 4, &pv, 4);
3775
3776 /* copy "user" */
3777 memcpy(packet + 8, "user", 4);
3778
3779 /* copy username */
3780 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3781
3782 free(curproxy->check_req);
3783 curproxy->check_req = packet;
3784 curproxy->check_len = packet_len;
3785
3786 packet_len = htonl(packet_len);
3787 memcpy(packet, &packet_len, 4);
3788 cur_arg += 2;
3789 } else {
3790 /* unknown suboption - catchall */
3791 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3792 file, linenum, args[0], args[1]);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796 } /* end while loop */
3797 }
3798 }
3799
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003800 else if (!strcmp(args[1], "redis-check")) {
3801 /* use REDIS PING request to check servers' health */
3802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3803 err_code |= ERR_WARN;
3804
3805 free(curproxy->check_req);
3806 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003807 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003808 curproxy->options2 |= PR_O2_REDIS_CHK;
3809
3810 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3811 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3812 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3813 }
3814
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003815 else if (!strcmp(args[1], "mysql-check")) {
3816 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003817 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3818 err_code |= ERR_WARN;
3819
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003820 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003821 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003822 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003823 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003824
3825 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3826 * const char mysql40_client_auth_pkt[] = {
3827 * "\x0e\x00\x00" // packet length
3828 * "\x01" // packet number
3829 * "\x00\x00" // client capabilities
3830 * "\x00\x00\x01" // max packet
3831 * "haproxy\x00" // username (null terminated string)
3832 * "\x00" // filler (always 0x00)
3833 * "\x01\x00\x00" // packet length
3834 * "\x00" // packet number
3835 * "\x01" // COM_QUIT command
3836 * };
3837 */
3838
3839 if (*(args[2])) {
3840 int cur_arg = 2;
3841
3842 while (*(args[cur_arg])) {
3843 if (strcmp(args[cur_arg], "user") == 0) {
3844 char *mysqluser;
3845 int packetlen, reqlen, userlen;
3846
3847 /* suboption header - needs additional argument for it */
3848 if (*(args[cur_arg+1]) == 0) {
3849 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3850 file, linenum, args[0], args[1], args[cur_arg]);
3851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
3853 }
3854 mysqluser = args[cur_arg + 1];
3855 userlen = strlen(mysqluser);
3856 packetlen = userlen + 7;
3857 reqlen = packetlen + 9;
3858
3859 free(curproxy->check_req);
3860 curproxy->check_req = (char *)calloc(1, reqlen);
3861 curproxy->check_len = reqlen;
3862
3863 snprintf(curproxy->check_req, 4, "%c%c%c",
3864 ((unsigned char) packetlen & 0xff),
3865 ((unsigned char) (packetlen >> 8) & 0xff),
3866 ((unsigned char) (packetlen >> 16) & 0xff));
3867
3868 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003869 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003870 curproxy->check_req[8] = 1;
3871 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3872 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3873 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3874 cur_arg += 2;
3875 } else {
3876 /* unknown suboption - catchall */
3877 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3878 file, linenum, args[0], args[1]);
3879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
3881 }
3882 } /* end while loop */
3883 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003884 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003885 else if (!strcmp(args[1], "ldap-check")) {
3886 /* use LDAP request to check servers' health */
3887 free(curproxy->check_req);
3888 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003889 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003890 curproxy->options2 |= PR_O2_LDAP_CHK;
3891
3892 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3893 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3894 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3895 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003896 else if (!strcmp(args[1], "tcp-check")) {
3897 /* use raw TCPCHK send/expect to check servers' health */
3898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3899 err_code |= ERR_WARN;
3900
3901 free(curproxy->check_req);
3902 curproxy->check_req = NULL;
3903 curproxy->options2 &= ~PR_O2_CHK_ANY;
3904 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3905 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003906 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003907 int cur_arg;
3908
3909 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3910 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003911 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003912
Willy Tarreau87cf5142011-08-19 22:57:24 +02003913 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003914
3915 free(curproxy->fwdfor_hdr_name);
3916 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3917 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3918
3919 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3920 cur_arg = 2;
3921 while (*(args[cur_arg])) {
3922 if (!strcmp(args[cur_arg], "except")) {
3923 /* suboption except - needs additional argument for it */
3924 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3925 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3926 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003929 }
3930 /* flush useless bits */
3931 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003932 cur_arg += 2;
3933 } else if (!strcmp(args[cur_arg], "header")) {
3934 /* suboption header - needs additional argument for it */
3935 if (*(args[cur_arg+1]) == 0) {
3936 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3937 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003940 }
3941 free(curproxy->fwdfor_hdr_name);
3942 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3943 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3944 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003945 } else if (!strcmp(args[cur_arg], "if-none")) {
3946 curproxy->options &= ~PR_O_FF_ALWAYS;
3947 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003948 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003949 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003950 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003951 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003954 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003955 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003956 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003957 else if (!strcmp(args[1], "originalto")) {
3958 int cur_arg;
3959
3960 /* insert x-original-to field, but not for the IP address listed as an except.
3961 * set default options (ie: bitfield, header name, etc)
3962 */
3963
3964 curproxy->options |= PR_O_ORGTO;
3965
3966 free(curproxy->orgto_hdr_name);
3967 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3968 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3969
Willy Tarreau87cf5142011-08-19 22:57:24 +02003970 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003971 cur_arg = 2;
3972 while (*(args[cur_arg])) {
3973 if (!strcmp(args[cur_arg], "except")) {
3974 /* suboption except - needs additional argument for it */
3975 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3976 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3977 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003980 }
3981 /* flush useless bits */
3982 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3983 cur_arg += 2;
3984 } else if (!strcmp(args[cur_arg], "header")) {
3985 /* suboption header - needs additional argument for it */
3986 if (*(args[cur_arg+1]) == 0) {
3987 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3988 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003991 }
3992 free(curproxy->orgto_hdr_name);
3993 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3994 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3995 cur_arg += 2;
3996 } else {
3997 /* unknown suboption - catchall */
3998 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3999 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004002 }
4003 } /* end while loop */
4004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 else {
4006 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 }
Willy Tarreau93893792009-07-23 13:19:11 +02004010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004012 else if (!strcmp(args[0], "default_backend")) {
4013 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004015
4016 if (*(args[1]) == 0) {
4017 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004020 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004021 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004022 curproxy->defbe.name = strdup(args[1]);
4023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004025 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004027
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004028 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4029 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 /* enable reconnections to dispatch */
4032 curproxy->options |= PR_O_REDISP;
4033 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004034 else if (!strcmp(args[0], "http-check")) {
4035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004037
4038 if (strcmp(args[1], "disable-on-404") == 0) {
4039 /* enable a graceful server shutdown on an HTTP 404 response */
4040 curproxy->options |= PR_O_DISABLE404;
4041 }
Willy Tarreauef781042010-01-27 11:53:01 +01004042 else if (strcmp(args[1], "send-state") == 0) {
4043 /* enable emission of the apparent state of a server in HTTP checks */
4044 curproxy->options2 |= PR_O2_CHK_SNDST;
4045 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004046 else if (strcmp(args[1], "expect") == 0) {
4047 const char *ptr_arg;
4048 int cur_arg;
4049
4050 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4051 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055
4056 cur_arg = 2;
4057 /* consider exclamation marks, sole or at the beginning of a word */
4058 while (*(ptr_arg = args[cur_arg])) {
4059 while (*ptr_arg == '!') {
4060 curproxy->options2 ^= PR_O2_EXP_INV;
4061 ptr_arg++;
4062 }
4063 if (*ptr_arg)
4064 break;
4065 cur_arg++;
4066 }
4067 /* now ptr_arg points to the beginning of a word past any possible
4068 * exclamation mark, and cur_arg is the argument which holds this word.
4069 */
4070 if (strcmp(ptr_arg, "status") == 0) {
4071 if (!*(args[cur_arg + 1])) {
4072 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4073 file, linenum, args[0], args[1], ptr_arg);
4074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004078 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004079 curproxy->expect_str = strdup(args[cur_arg + 1]);
4080 }
4081 else if (strcmp(ptr_arg, "string") == 0) {
4082 if (!*(args[cur_arg + 1])) {
4083 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4084 file, linenum, args[0], args[1], ptr_arg);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
4088 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004089 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004090 curproxy->expect_str = strdup(args[cur_arg + 1]);
4091 }
4092 else if (strcmp(ptr_arg, "rstatus") == 0) {
4093 if (!*(args[cur_arg + 1])) {
4094 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4095 file, linenum, args[0], args[1], ptr_arg);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
4099 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004100 free(curproxy->expect_str);
4101 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4102 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004103 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4104 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4105 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4106 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110 }
4111 else if (strcmp(ptr_arg, "rstring") == 0) {
4112 if (!*(args[cur_arg + 1])) {
4113 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4114 file, linenum, args[0], args[1], ptr_arg);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004119 free(curproxy->expect_str);
4120 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4121 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004122 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4123 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4124 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4125 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 }
4130 else {
4131 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4132 file, linenum, args[0], args[1], ptr_arg);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004137 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004138 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 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004141 }
4142 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004143 else if (!strcmp(args[0], "tcp-check")) {
4144 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4145 err_code |= ERR_WARN;
4146
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004147 if (strcmp(args[1], "connect") == 0) {
4148 const char *ptr_arg;
4149 int cur_arg;
4150 struct tcpcheck_rule *tcpcheck;
4151 struct list *l;
4152
4153 /* check if first rule is also a 'connect' action */
4154 l = (struct list *)&curproxy->tcpcheck_rules;
4155 if (l->p != l->n) {
4156 tcpcheck = (struct tcpcheck_rule *)l->n;
4157 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4158 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4159 file, linenum);
4160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
4162 }
4163 }
4164
4165 cur_arg = 2;
4166 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4167 tcpcheck->action = TCPCHK_ACT_CONNECT;
4168
4169 /* parsing each parameters to fill up the rule */
4170 while (*(ptr_arg = args[cur_arg])) {
4171 /* tcp port */
4172 if (strcmp(args[cur_arg], "port") == 0) {
4173 if ( (atol(args[cur_arg + 1]) > 65535) ||
4174 (atol(args[cur_arg + 1]) < 1) ){
4175 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4176 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
4180 tcpcheck->port = atol(args[cur_arg + 1]);
4181 cur_arg += 2;
4182 }
4183 /* send proxy protocol */
4184 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4185 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4186 cur_arg++;
4187 }
4188#ifdef USE_OPENSSL
4189 else if (strcmp(args[cur_arg], "ssl") == 0) {
4190 curproxy->options |= PR_O_TCPCHK_SSL;
4191 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4192 cur_arg++;
4193 }
4194#endif /* USE_OPENSSL */
4195 else {
4196#ifdef USE_OPENSSL
4197 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4198#else /* USE_OPENSSL */
4199 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4200#endif /* USE_OPENSSL */
4201 file, linenum, args[0], args[1], args[cur_arg]);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
4205
4206 }
4207
4208 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4209 }
4210 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004211 if (! *(args[2]) ) {
4212 /* SEND string expected */
4213 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4214 file, linenum, args[0], args[1], args[2]);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217 } else {
4218 struct tcpcheck_rule *tcpcheck;
4219
4220 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4221
4222 tcpcheck->action = TCPCHK_ACT_SEND;
4223 tcpcheck->string_len = strlen(args[2]);
4224 tcpcheck->string = strdup(args[2]);
4225 tcpcheck->expect_regex = NULL;
4226
4227 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4228 }
4229 }
4230 else if (strcmp(args[1], "send-binary") == 0) {
4231 if (! *(args[2]) ) {
4232 /* SEND binary string expected */
4233 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4234 file, linenum, args[0], args[1], args[2]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 } else {
4238 struct tcpcheck_rule *tcpcheck;
4239 char *err = NULL;
4240
4241 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4242
4243 tcpcheck->action = TCPCHK_ACT_SEND;
4244 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4245 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4246 file, linenum, args[0], args[1], args[2], err);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250 tcpcheck->expect_regex = NULL;
4251
4252 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4253 }
4254 }
4255 else if (strcmp(args[1], "expect") == 0) {
4256 const char *ptr_arg;
4257 int cur_arg;
4258 int inverse = 0;
4259
4260 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4261 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265
4266 cur_arg = 2;
4267 /* consider exclamation marks, sole or at the beginning of a word */
4268 while (*(ptr_arg = args[cur_arg])) {
4269 while (*ptr_arg == '!') {
4270 inverse = !inverse;
4271 ptr_arg++;
4272 }
4273 if (*ptr_arg)
4274 break;
4275 cur_arg++;
4276 }
4277 /* now ptr_arg points to the beginning of a word past any possible
4278 * exclamation mark, and cur_arg is the argument which holds this word.
4279 */
4280 if (strcmp(ptr_arg, "binary") == 0) {
4281 if (!*(args[cur_arg + 1])) {
4282 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4283 file, linenum, args[0], args[1], ptr_arg);
4284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
4287 struct tcpcheck_rule *tcpcheck;
4288 char *err = NULL;
4289
4290 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4291
4292 tcpcheck->action = TCPCHK_ACT_EXPECT;
4293 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4294 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4295 file, linenum, args[0], args[1], args[2], err);
4296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299 tcpcheck->expect_regex = NULL;
4300 tcpcheck->inverse = inverse;
4301
4302 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4303 }
4304 else if (strcmp(ptr_arg, "string") == 0) {
4305 if (!*(args[cur_arg + 1])) {
4306 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4307 file, linenum, args[0], args[1], ptr_arg);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 struct tcpcheck_rule *tcpcheck;
4312
4313 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4314
4315 tcpcheck->action = TCPCHK_ACT_EXPECT;
4316 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4317 tcpcheck->string = strdup(args[cur_arg + 1]);
4318 tcpcheck->expect_regex = NULL;
4319 tcpcheck->inverse = inverse;
4320
4321 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4322 }
4323 else if (strcmp(ptr_arg, "rstring") == 0) {
4324 if (!*(args[cur_arg + 1])) {
4325 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4326 file, linenum, args[0], args[1], ptr_arg);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330 struct tcpcheck_rule *tcpcheck;
4331
4332 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4333
4334 tcpcheck->action = TCPCHK_ACT_EXPECT;
4335 tcpcheck->string_len = 0;
4336 tcpcheck->string = NULL;
4337 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4338 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4339 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4340 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
4344 tcpcheck->inverse = inverse;
4345
4346 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4347 }
4348 else {
4349 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4350 file, linenum, args[0], args[1], ptr_arg);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354 }
4355 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004356 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004361 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004362 if (curproxy == &defproxy) {
4363 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004366 }
4367
Willy Tarreaub80c2302007-11-30 20:51:32 +01004368 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004370
4371 if (strcmp(args[1], "fail") == 0) {
4372 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004373 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004374 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4375 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004378 }
4379
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004380 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4381 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4382 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004385 }
4386 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4387 }
4388 else {
4389 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004392 }
4393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394#ifdef TPROXY
4395 else if (!strcmp(args[0], "transparent")) {
4396 /* enable transparent proxy connections */
4397 curproxy->options |= PR_O_TRANSP;
4398 }
4399#endif
4400 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004401 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004403
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 if (*(args[1]) == 0) {
4405 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004408 }
4409 curproxy->maxconn = atol(args[1]);
4410 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004411 else if (!strcmp(args[0], "backlog")) { /* backlog */
4412 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004414
4415 if (*(args[1]) == 0) {
4416 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004419 }
4420 curproxy->backlog = atol(args[1]);
4421 }
Willy Tarreau86034312006-12-29 00:10:33 +01004422 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004425
Willy Tarreau86034312006-12-29 00:10:33 +01004426 if (*(args[1]) == 0) {
4427 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004430 }
4431 curproxy->fullconn = atol(args[1]);
4432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4434 if (*(args[1]) == 0) {
4435 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004439 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4440 if (err) {
4441 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4442 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004445 }
4446 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 }
4448 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004449 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004450 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004451 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004452
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 if (curproxy == &defproxy) {
4454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004458 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004460
Willy Tarreau902636f2013-03-10 19:44:48 +01004461 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004462 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004463 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004464 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004465 goto out;
4466 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004467
4468 proto = protocol_by_family(sk->ss_family);
4469 if (!proto || !proto->connect) {
4470 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4471 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
4474 }
4475
4476 if (port1 != port2) {
4477 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4478 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004482
4483 if (!port1) {
4484 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4485 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
4488 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004489
Willy Tarreaud5191e72010-02-09 20:50:45 +01004490 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004491 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 }
4493 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004494 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004495 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004496
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004497 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4498 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004503 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004504 /**
4505 * The syntax for hash-type config element is
4506 * hash-type {map-based|consistent} [[<algo>] avalanche]
4507 *
4508 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4509 */
4510 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004511
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4513 err_code |= ERR_WARN;
4514
4515 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004516 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4517 }
4518 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004519 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4520 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004521 else if (strcmp(args[1], "avalanche") == 0) {
4522 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]);
4523 err_code |= ERR_ALERT | ERR_FATAL;
4524 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004525 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004526 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004527 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004528 err_code |= ERR_ALERT | ERR_FATAL;
4529 goto out;
4530 }
Bhaskar98634f02013-10-29 23:30:51 -04004531
4532 /* set the hash function to use */
4533 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004534 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004535 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004536
4537 /* if consistent with no argument, then avalanche modifier is also applied */
4538 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4539 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004540 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004541 /* set the hash function */
4542 if (!strcmp(args[2], "sdbm")) {
4543 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4544 }
4545 else if (!strcmp(args[2], "djb2")) {
4546 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004547 } else if (!strcmp(args[2], "wt6")) {
4548 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004549 }
4550 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004551 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 -05004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555
4556 /* set the hash modifier */
4557 if (!strcmp(args[3], "avalanche")) {
4558 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4559 }
4560 else if (*args[3]) {
4561 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
4564 }
Bhaskar98634f02013-10-29 23:30:51 -04004565 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004566 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004567 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004569 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004570 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004572 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004577 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579
4580 if (!*args[2]) {
4581 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_ALERT | ERR_FATAL;
4584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004585 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004586
4587 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004588 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004589 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4590 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004593 }
4594
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004595 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004596 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004597 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004598 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004599
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004600 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4601 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4602 err_code |= ERR_ALERT | ERR_ABORT;
4603 goto out;
4604 }
4605
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004606 /* the servers are linked backwards first */
4607 newsrv->next = curproxy->srv;
4608 curproxy->srv = newsrv;
4609 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004610 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004611 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004613 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004614 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004615 LIST_INIT(&newsrv->pendconns);
4616 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004617 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004618 newsrv->state = SRV_RUNNING; /* early server setup */
4619 newsrv->last_change = now.tv_sec;
4620 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004622 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004623 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004624 * - IP: => port=+0, relative
4625 * - IP:N => port=N, absolute
4626 * - IP:+N => port=+N, relative
4627 * - IP:-N => port=-N, relative
4628 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004629 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004630 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004631 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004632 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004633 goto out;
4634 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004635
4636 proto = protocol_by_family(sk->ss_family);
4637 if (!proto || !proto->connect) {
4638 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4639 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004643
4644 if (!port1 || !port2) {
4645 /* no port specified, +offset, -offset */
4646 newsrv->state |= SRV_MAPPORTS;
4647 }
4648 else if (port1 != port2) {
4649 /* port range */
4650 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4651 file, linenum, args[0], args[1], args[2]);
4652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
4654 }
4655 else {
4656 /* used by checks */
4657 realport = port1;
4658 }
4659
Willy Tarreaud5191e72010-02-09 20:50:45 +01004660 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004661 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4662 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004663
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004664 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004665 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4666 file, linenum, newsrv->addr.ss_family, args[2]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004670
Simon Hormand60d6912013-11-25 10:46:36 +09004671 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004672 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004673 newsrv->check.inter = curproxy->defsrv.check.inter;
4674 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4675 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004676 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4677 newsrv->agent.port = curproxy->defsrv.agent.port;
4678 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4679 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4680 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004681 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4682 newsrv->minconn = curproxy->defsrv.minconn;
4683 newsrv->maxconn = curproxy->defsrv.maxconn;
4684 newsrv->slowstart = curproxy->defsrv.slowstart;
4685 newsrv->onerror = curproxy->defsrv.onerror;
4686 newsrv->consecutive_errors_limit
4687 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004688#ifdef OPENSSL
4689 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4690#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004691 newsrv->uweight = newsrv->iweight
4692 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004693
Simon Horman69d29f92013-02-23 15:14:19 +09004694 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004695 newsrv->check.rise = curproxy->defsrv.check.rise;
4696 newsrv->check.fall = curproxy->defsrv.check.fall;
4697 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004698 newsrv->check.server = newsrv;
4699
Simon Hormand60d6912013-11-25 10:46:36 +09004700 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004701 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4702 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4703 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004704 newsrv->agent.server = newsrv;
4705
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004706 cur_arg = 3;
4707 } else {
4708 newsrv = &curproxy->defsrv;
4709 cur_arg = 1;
4710 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004711
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004713 if (!strcmp(args[cur_arg], "agent-check")) {
4714 global.maxsock++;
4715 do_agent = 1;
4716 cur_arg += 1;
4717 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4718 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4719 if (err) {
4720 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4721 file, linenum, *err, newsrv->id);
4722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
4725 if (val <= 0) {
4726 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4727 file, linenum, val, args[cur_arg], newsrv->id);
4728 err_code |= ERR_ALERT | ERR_FATAL;
4729 goto out;
4730 }
4731 newsrv->agent.inter = val;
4732 cur_arg += 2;
4733 }
4734 else if (!strcmp(args[cur_arg], "agent-port")) {
4735 global.maxsock++;
4736 newsrv->agent.port = atol(args[cur_arg + 1]);
4737 cur_arg += 2;
4738 }
4739 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004740 newsrv->cookie = strdup(args[cur_arg + 1]);
4741 newsrv->cklen = strlen(args[cur_arg + 1]);
4742 cur_arg += 2;
4743 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004744 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004745 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4746 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4747 cur_arg += 2;
4748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004750 if (!*args[cur_arg + 1]) {
4751 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4752 file, linenum, args[cur_arg]);
4753 err_code |= ERR_ALERT | ERR_FATAL;
4754 goto out;
4755 }
4756
Simon Horman58c32972013-11-25 10:46:38 +09004757 newsrv->check.rise = atol(args[cur_arg + 1]);
4758 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004759 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4760 file, linenum, args[cur_arg]);
4761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
4763 }
4764
Simon Horman125d0992013-02-24 17:23:38 +09004765 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004766 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004767 cur_arg += 2;
4768 }
4769 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004770 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004771
4772 if (!*args[cur_arg + 1]) {
4773 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4774 file, linenum, args[cur_arg]);
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
4778
Simon Horman58c32972013-11-25 10:46:38 +09004779 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004780 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4781 file, linenum, args[cur_arg]);
4782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
4784 }
4785
Willy Tarreaubaaee002006-06-26 02:48:02 +02004786 cur_arg += 2;
4787 }
4788 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004789 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4790 if (err) {
4791 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4792 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004793 err_code |= ERR_ALERT | ERR_FATAL;
4794 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004795 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004796 if (val <= 0) {
4797 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4798 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004801 }
Simon Horman66183002013-02-23 10:16:43 +09004802 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004803 cur_arg += 2;
4804 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004805 else if (!strcmp(args[cur_arg], "fastinter")) {
4806 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4807 if (err) {
4808 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4809 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004812 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004813 if (val <= 0) {
4814 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4815 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004816 err_code |= ERR_ALERT | ERR_FATAL;
4817 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004818 }
Simon Horman66183002013-02-23 10:16:43 +09004819 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004820 cur_arg += 2;
4821 }
4822 else if (!strcmp(args[cur_arg], "downinter")) {
4823 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4824 if (err) {
4825 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4826 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004827 err_code |= ERR_ALERT | ERR_FATAL;
4828 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004829 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004830 if (val <= 0) {
4831 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4832 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004835 }
Simon Horman66183002013-02-23 10:16:43 +09004836 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004837 cur_arg += 2;
4838 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004839 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004840 struct sockaddr_storage *sk;
4841 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004842 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004843
Willy Tarreau902636f2013-03-10 19:44:48 +01004844 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004845 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004846 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004847 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004848 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004849 goto out;
4850 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004851
4852 proto = protocol_by_family(sk->ss_family);
4853 if (!proto || !proto->connect) {
4854 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004855 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004856 err_code |= ERR_ALERT | ERR_FATAL;
4857 goto out;
4858 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004859
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004860 if (port1 != port2) {
4861 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4862 file, linenum, args[cur_arg], args[cur_arg + 1]);
4863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
4866
Simon Horman66183002013-02-23 10:16:43 +09004867 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004868 cur_arg += 2;
4869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004870 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004871 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 cur_arg += 2;
4873 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004874 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 newsrv->state |= SRV_BACKUP;
4876 cur_arg ++;
4877 }
Simon Hormanfa461682011-06-25 09:39:49 +09004878 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4879 newsrv->state |= SRV_NON_STICK;
4880 cur_arg ++;
4881 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004882 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4883 newsrv->state |= SRV_SEND_PROXY;
4884 cur_arg ++;
4885 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004886 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4887 newsrv->check.send_proxy = 1;
4888 cur_arg ++;
4889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004890 else if (!strcmp(args[cur_arg], "weight")) {
4891 int w;
4892 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004893 if (w < 0 || w > SRV_UWGHT_MAX) {
4894 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4895 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004896 err_code |= ERR_ALERT | ERR_FATAL;
4897 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004898 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004899 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 cur_arg += 2;
4901 }
4902 else if (!strcmp(args[cur_arg], "minconn")) {
4903 newsrv->minconn = atol(args[cur_arg + 1]);
4904 cur_arg += 2;
4905 }
4906 else if (!strcmp(args[cur_arg], "maxconn")) {
4907 newsrv->maxconn = atol(args[cur_arg + 1]);
4908 cur_arg += 2;
4909 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004910 else if (!strcmp(args[cur_arg], "maxqueue")) {
4911 newsrv->maxqueue = atol(args[cur_arg + 1]);
4912 cur_arg += 2;
4913 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004914 else if (!strcmp(args[cur_arg], "slowstart")) {
4915 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004916 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004917 if (err) {
4918 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4919 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004922 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004923 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004924 cur_arg += 2;
4925 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004926 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004927
4928 if (!*args[cur_arg + 1]) {
4929 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4930 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004933 }
4934
4935 newsrv->trackit = strdup(args[cur_arg + 1]);
4936
4937 cur_arg += 2;
4938 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004939 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004940 global.maxsock++;
4941 do_check = 1;
4942 cur_arg += 1;
4943 }
Willy Tarreau96839092010-03-29 10:02:24 +02004944 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4945 newsrv->state |= SRV_MAINTAIN;
4946 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004947 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004948 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004949 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004950 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004951 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004952 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004953 if (!strcmp(args[cur_arg + 1], "none"))
4954 newsrv->observe = HANA_OBS_NONE;
4955 else if (!strcmp(args[cur_arg + 1], "layer4"))
4956 newsrv->observe = HANA_OBS_LAYER4;
4957 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4958 if (curproxy->mode != PR_MODE_HTTP) {
4959 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4960 file, linenum, args[cur_arg + 1]);
4961 err_code |= ERR_ALERT;
4962 }
4963 newsrv->observe = HANA_OBS_LAYER7;
4964 }
4965 else {
4966 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004967 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004968 file, linenum, args[cur_arg], args[cur_arg + 1]);
4969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
4971 }
4972
4973 cur_arg += 2;
4974 }
4975 else if (!strcmp(args[cur_arg], "on-error")) {
4976 if (!strcmp(args[cur_arg + 1], "fastinter"))
4977 newsrv->onerror = HANA_ONERR_FASTINTER;
4978 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4979 newsrv->onerror = HANA_ONERR_FAILCHK;
4980 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4981 newsrv->onerror = HANA_ONERR_SUDDTH;
4982 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4983 newsrv->onerror = HANA_ONERR_MARKDWN;
4984 else {
4985 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004986 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004987 file, linenum, args[cur_arg], args[cur_arg + 1]);
4988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
4990 }
4991
4992 cur_arg += 2;
4993 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004994 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4995 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4996 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4997 else {
4998 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4999 file, linenum, args[cur_arg], args[cur_arg + 1]);
5000 err_code |= ERR_ALERT | ERR_FATAL;
5001 goto out;
5002 }
5003
5004 cur_arg += 2;
5005 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07005006 else if (!strcmp(args[cur_arg], "on-marked-up")) {
5007 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
5008 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
5009 else {
5010 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
5011 file, linenum, args[cur_arg], args[cur_arg + 1]);
5012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
5014 }
5015
5016 cur_arg += 2;
5017 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005018 else if (!strcmp(args[cur_arg], "error-limit")) {
5019 if (!*args[cur_arg + 1]) {
5020 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
5021 file, linenum, args[cur_arg]);
5022 err_code |= ERR_ALERT | ERR_FATAL;
5023 goto out;
5024 }
5025
5026 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
5027
5028 if (newsrv->consecutive_errors_limit <= 0) {
5029 Alert("parsing [%s:%d]: %s has to be > 0.\n",
5030 file, linenum, args[cur_arg]);
5031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
5033 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01005034 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005035 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005036 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005037 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005038 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005039 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01005040
Willy Tarreaubaaee002006-06-26 02:48:02 +02005041 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01005042 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
5043 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005044 err_code |= ERR_ALERT | ERR_FATAL;
5045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005046 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005047
Willy Tarreauef9a3602012-12-08 22:29:20 +01005048 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01005049 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005050 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005051 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005052 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005053 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005054 goto out;
5055 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005056
5057 proto = protocol_by_family(sk->ss_family);
5058 if (!proto || !proto->connect) {
5059 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5060 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005061 err_code |= ERR_ALERT | ERR_FATAL;
5062 goto out;
5063 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005064
Willy Tarreauef9a3602012-12-08 22:29:20 +01005065 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005066
5067 if (port_low != port_high) {
5068 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005069
5070 if (!port_low || !port_high) {
5071 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
5072 file, linenum, args[cur_arg], args[cur_arg + 1]);
5073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
5075 }
5076
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005077 if (port_low <= 0 || port_low > 65535 ||
5078 port_high <= 0 || port_high > 65535 ||
5079 port_low > port_high) {
5080 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
5081 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02005082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005084 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005085 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
5086 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
5087 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005088 }
5089
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005091 while (*(args[cur_arg])) {
5092 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005093#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5094#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005095 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01005096 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
5097 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005098 err_code |= ERR_ALERT | ERR_FATAL;
5099 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005100 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005101#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005102 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005103 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01005104 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005107 }
5108 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005109 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5110 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005111 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005112 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5113 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005114 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5115 char *name, *end;
5116
5117 name = args[cur_arg+1] + 7;
5118 while (isspace(*name))
5119 name++;
5120
5121 end = name;
5122 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5123 end++;
5124
Willy Tarreauef9a3602012-12-08 22:29:20 +01005125 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5126 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5127 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5128 newsrv->conn_src.bind_hdr_len = end - name;
5129 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5130 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5131 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005132
5133 /* now look for an occurrence number */
5134 while (isspace(*end))
5135 end++;
5136 if (*end == ',') {
5137 end++;
5138 name = end;
5139 if (*end == '-')
5140 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005141 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005142 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005143 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005144 }
5145
Willy Tarreauef9a3602012-12-08 22:29:20 +01005146 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005147 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5148 " occurrences values smaller than %d.\n",
5149 file, linenum, MAX_HDR_HISTORY);
5150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
5152 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005153 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005154 struct sockaddr_storage *sk;
5155 int port1, port2;
5156
Willy Tarreau902636f2013-03-10 19:44:48 +01005157 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005158 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005159 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005160 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005161 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005162 goto out;
5163 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005164
5165 proto = protocol_by_family(sk->ss_family);
5166 if (!proto || !proto->connect) {
5167 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5168 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
5171 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005172
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005173 if (port1 != port2) {
5174 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5175 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005176 err_code |= ERR_ALERT | ERR_FATAL;
5177 goto out;
5178 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005179 newsrv->conn_src.tproxy_addr = *sk;
5180 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005181 }
5182 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005183#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005184 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005185#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005186 cur_arg += 2;
5187 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005188#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005189 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005190 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005193#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005194 } /* "usesrc" */
5195
5196 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5197#ifdef SO_BINDTODEVICE
5198 if (!*args[cur_arg + 1]) {
5199 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5200 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005201 err_code |= ERR_ALERT | ERR_FATAL;
5202 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005203 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005204 free(newsrv->conn_src.iface_name);
5205 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5206 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005207 global.last_checks |= LSTCHK_NETADM;
5208#else
5209 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5210 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005213#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005214 cur_arg += 2;
5215 continue;
5216 }
5217 /* this keyword in not an option of "source" */
5218 break;
5219 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005221 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005222 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5223 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005227 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005228 static int srv_dumped;
5229 struct srv_kw *kw;
5230 char *err;
5231
5232 kw = srv_find_kw(args[cur_arg]);
5233 if (kw) {
5234 char *err = NULL;
5235 int code;
5236
5237 if (!kw->parse) {
5238 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5239 file, linenum, args[0], args[1], args[cur_arg]);
5240 cur_arg += 1 + kw->skip ;
5241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
5243 }
5244
5245 if (defsrv && !kw->default_ok) {
5246 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5247 file, linenum, args[0], args[1], args[cur_arg]);
5248 cur_arg += 1 + kw->skip ;
5249 err_code |= ERR_ALERT;
5250 continue;
5251 }
5252
5253 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5254 err_code |= code;
5255
5256 if (code) {
5257 if (err && *err) {
5258 indent_msg(&err, 2);
5259 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5260 }
5261 else
5262 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5263 file, linenum, args[0], args[1], args[cur_arg]);
5264 if (code & ERR_FATAL) {
5265 free(err);
5266 cur_arg += 1 + kw->skip;
5267 goto out;
5268 }
5269 }
5270 free(err);
5271 cur_arg += 1 + kw->skip;
5272 continue;
5273 }
5274
5275 err = NULL;
5276 if (!srv_dumped) {
5277 srv_dump_kws(&err);
5278 indent_msg(&err, 4);
5279 srv_dumped = 1;
5280 }
5281
5282 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5283 file, linenum, args[0], args[1], args[cur_arg],
5284 err ? " Registered keywords :" : "", err ? err : "");
5285 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005286
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
5290 }
5291
Simon Horman8c3d0be2013-11-25 10:46:40 +09005292 /* Set initial drain state using now-configured weight */
5293 set_server_drain_state(newsrv);
5294
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005296 int ret;
5297
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005298 if (newsrv->trackit) {
5299 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5300 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005301 err_code |= ERR_ALERT | ERR_FATAL;
5302 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005303 }
5304
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005305 /* If neither a port nor an addr was specified and no check transport
5306 * layer is forced, then the transport layer used by the checks is the
5307 * same as for the production traffic. Otherwise we use raw_sock by
5308 * default, unless one is specified.
5309 */
Simon Horman66183002013-02-23 10:16:43 +09005310 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005311#ifdef USE_OPENSSL
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005312 newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
Willy Tarreau71516332012-10-10 23:01:14 +02005313#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005314 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5315 }
Simon Horman66183002013-02-23 10:16:43 +09005316 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005317 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005318 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005319
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005320 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005321 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005322
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005323 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005324 /* not yet valid, because no port was set on
5325 * the server either. We'll check if we have
5326 * a known port on the first listener.
5327 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005328 struct listener *l;
5329
5330 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005331 newsrv->check.port = get_host_port(&l->addr);
5332 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005333 break;
5334 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005335 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005336 /*
5337 * We need at least a service port, a check port or the first tcp-check rule must
5338 * be a 'connect' one
5339 */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005340 if (!newsrv->check.port) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005341 struct tcpcheck_rule *n = NULL, *r = NULL;
5342 struct list *l;
5343
5344 r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
5345 if (!r) {
5346 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5347 file, linenum, newsrv->id);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351 if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
5352 Alert("parsing [%s:%d] : server %s has neither service port nor check port nor tcp_check rule 'connect' with port information. Check has been disabled.\n",
5353 file, linenum, newsrv->id);
5354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
5356 }
5357 else {
5358 /* scan the tcp-check ruleset to ensure a port has been configured */
5359 l = &newsrv->proxy->tcpcheck_rules;
5360 list_for_each_entry(n, l, list) {
5361 r = (struct tcpcheck_rule *)n->list.p;
5362 if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
5363 Alert("parsing [%s:%d] : server %s has neither service port nor check port, and a tcp_check rule 'connect' with no port information. Check has been disabled.\n",
5364 file, linenum, newsrv->id);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368 }
5369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005371
Willy Tarreau2f075e92013-12-03 11:11:34 +01005372 /* note: check type will be set during the config review phase */
5373 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005374 if (ret) {
5375 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005376 goto out;
5377 }
5378
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005379 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005380 }
5381
Simon Hormand60d6912013-11-25 10:46:36 +09005382 if (do_agent) {
5383 int ret;
5384
5385 if (!newsrv->agent.port) {
5386 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5387 file, linenum, newsrv->id);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
5391
5392 if (!newsrv->agent.inter)
5393 newsrv->agent.inter = newsrv->check.inter;
5394
5395 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5396 if (ret) {
5397 err_code |= ret;
5398 goto out;
5399 }
5400
Willy Tarreau33434322013-12-11 21:15:19 +01005401 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005402 }
5403
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005404 if (!defsrv) {
5405 if (newsrv->state & SRV_BACKUP)
5406 curproxy->srv_bck++;
5407 else
5408 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005409
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005410 newsrv->prev_state = newsrv->state;
5411 }
William Lallemanda73203e2012-03-12 12:48:57 +01005412 }
5413
5414 else if (strcmp(args[0], "unique-id-format") == 0) {
5415 if (!*(args[1])) {
5416 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
William Lallemand3203ff42012-11-11 17:30:56 +01005420 if (*(args[2])) {
5421 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
5424 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005425 free(curproxy->conf.uniqueid_format_string);
5426 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005427
Willy Tarreau62a61232013-04-12 18:13:46 +02005428 free(curproxy->conf.uif_file);
5429 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5430 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005431 }
William Lallemanda73203e2012-03-12 12:48:57 +01005432
5433 else if (strcmp(args[0], "unique-id-header") == 0) {
5434 if (!*(args[1])) {
5435 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5436 err_code |= ERR_ALERT | ERR_FATAL;
5437 goto out;
5438 }
5439 free(curproxy->header_unique_id);
5440 curproxy->header_unique_id = strdup(args[1]);
5441 }
5442
William Lallemand723b73a2012-02-08 16:37:49 +01005443 else if (strcmp(args[0], "log-format") == 0) {
5444 if (!*(args[1])) {
5445 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
5448 }
William Lallemand3203ff42012-11-11 17:30:56 +01005449 if (*(args[2])) {
5450 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
5453 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005454
Willy Tarreau62a61232013-04-12 18:13:46 +02005455 if (curproxy->conf.logformat_string != default_http_log_format &&
5456 curproxy->conf.logformat_string != default_tcp_log_format &&
5457 curproxy->conf.logformat_string != clf_http_log_format)
5458 free(curproxy->conf.logformat_string);
5459 curproxy->conf.logformat_string = strdup(args[1]);
5460
5461 free(curproxy->conf.lfs_file);
5462 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5463 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005464
5465 /* get a chance to improve log-format error reporting by
5466 * reporting the correct line-number when possible.
5467 */
5468 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5469 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5470 file, linenum, curproxy->id);
5471 err_code |= ERR_WARN;
5472 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005473 }
William Lallemand723b73a2012-02-08 16:37:49 +01005474
William Lallemand0f99e342011-10-12 17:50:54 +02005475 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5476 /* delete previous herited or defined syslog servers */
5477 struct logsrv *back;
5478
5479 if (*(args[1]) != 0) {
5480 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5481 err_code |= ERR_ALERT | ERR_FATAL;
5482 goto out;
5483 }
5484
William Lallemand723b73a2012-02-08 16:37:49 +01005485 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5486 LIST_DEL(&tmplogsrv->list);
5487 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005488 }
5489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005491 struct logsrv *logsrv;
5492
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005494 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005495 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005496 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005497 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005498 LIST_INIT(&node->list);
5499 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005501 }
5502 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005503 struct sockaddr_storage *sk;
5504 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005505
5506 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507
William Lallemand0f99e342011-10-12 17:50:54 +02005508 logsrv->facility = get_log_facility(args[2]);
5509 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005511 err_code |= ERR_ALERT | ERR_FATAL;
5512 goto out;
5513
Willy Tarreaubaaee002006-06-26 02:48:02 +02005514 }
5515
William Lallemand0f99e342011-10-12 17:50:54 +02005516 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005518 logsrv->level = get_log_level(args[3]);
5519 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
5523
Willy Tarreaubaaee002006-06-26 02:48:02 +02005524 }
5525 }
5526
William Lallemand0f99e342011-10-12 17:50:54 +02005527 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005528 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005529 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005530 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005531 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005532 err_code |= ERR_ALERT | ERR_FATAL;
5533 goto out;
5534
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005535 }
5536 }
5537
Willy Tarreau902636f2013-03-10 19:44:48 +01005538 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005539 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005540 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005541 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005542 goto out;
5543 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005544
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005545 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005546
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005547 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005548 if (port1 != port2) {
5549 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5550 file, linenum, args[0], args[1]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005555 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005556 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 }
William Lallemand0f99e342011-10-12 17:50:54 +02005558
5559 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005560 }
5561 else {
5562 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5563 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 }
5567 }
5568 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005569 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005570 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005571 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005572 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005573
Willy Tarreau977b8e42006-12-29 14:19:17 +01005574 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005575 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005576
Willy Tarreaubaaee002006-06-26 02:48:02 +02005577 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005578 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5579 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005580 err_code |= ERR_ALERT | ERR_FATAL;
5581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005583
5584 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005585 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5586 free(curproxy->conn_src.iface_name);
5587 curproxy->conn_src.iface_name = NULL;
5588 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005589
Willy Tarreau902636f2013-03-10 19:44:48 +01005590 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005591 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005592 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005593 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005594 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005595 goto out;
5596 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005597
5598 proto = protocol_by_family(sk->ss_family);
5599 if (!proto || !proto->connect) {
5600 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005601 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005605
5606 if (port1 != port2) {
5607 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5608 file, linenum, args[0], args[1]);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
5612
Willy Tarreauef9a3602012-12-08 22:29:20 +01005613 curproxy->conn_src.source_addr = *sk;
5614 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005615
5616 cur_arg = 2;
5617 while (*(args[cur_arg])) {
5618 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005619#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5620#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005621 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005622 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5623 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
5625 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005626 }
5627#endif
5628 if (!*args[cur_arg + 1]) {
5629 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5630 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005633 }
5634
5635 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005636 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5637 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005638 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005639 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5640 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005641 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5642 char *name, *end;
5643
5644 name = args[cur_arg+1] + 7;
5645 while (isspace(*name))
5646 name++;
5647
5648 end = name;
5649 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5650 end++;
5651
Willy Tarreauef9a3602012-12-08 22:29:20 +01005652 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5653 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5654 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5655 curproxy->conn_src.bind_hdr_len = end - name;
5656 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5657 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5658 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005659
5660 /* now look for an occurrence number */
5661 while (isspace(*end))
5662 end++;
5663 if (*end == ',') {
5664 end++;
5665 name = end;
5666 if (*end == '-')
5667 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005668 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005669 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005670 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005671 }
5672
Willy Tarreauef9a3602012-12-08 22:29:20 +01005673 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005674 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5675 " occurrences values smaller than %d.\n",
5676 file, linenum, MAX_HDR_HISTORY);
5677 err_code |= ERR_ALERT | ERR_FATAL;
5678 goto out;
5679 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005680 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005681 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005682
Willy Tarreau902636f2013-03-10 19:44:48 +01005683 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005684 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005685 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005686 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005687 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005688 goto out;
5689 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005690
5691 proto = protocol_by_family(sk->ss_family);
5692 if (!proto || !proto->connect) {
5693 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5694 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005695 err_code |= ERR_ALERT | ERR_FATAL;
5696 goto out;
5697 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005698
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005699 if (port1 != port2) {
5700 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5701 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005705 curproxy->conn_src.tproxy_addr = *sk;
5706 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005707 }
5708 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005709#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005710 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005711#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005712#else /* no TPROXY support */
5713 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005714 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005717#endif
5718 cur_arg += 2;
5719 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005720 }
5721
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005722 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5723#ifdef SO_BINDTODEVICE
5724 if (!*args[cur_arg + 1]) {
5725 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005729 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005730 free(curproxy->conn_src.iface_name);
5731 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5732 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005733 global.last_checks |= LSTCHK_NETADM;
5734#else
5735 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5736 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005737 err_code |= ERR_ALERT | ERR_FATAL;
5738 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005739#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005740 cur_arg += 2;
5741 continue;
5742 }
5743 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005744 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005749 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5750 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5751 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005752 err_code |= ERR_ALERT | ERR_FATAL;
5753 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005754 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005756 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5758 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005759 err_code |= ERR_ALERT | ERR_FATAL;
5760 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005762
5763 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005764 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005765 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005766 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005768 }
5769 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005770 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005771 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005772 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005773 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005775 }
5776 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005777 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005778 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005779 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005780 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005782 }
5783 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005784 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005785 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005786 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005787 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005789 }
5790 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005791 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005792 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005793 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005794 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005797 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005798 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005799 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005800 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005801 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005802 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005803 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005804 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005805 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005806 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005807 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005808 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005809 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005810 }
5811 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005812 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005813 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005814 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005815 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005816 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005817 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005818 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005819 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5821 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005822 err_code |= ERR_ALERT | ERR_FATAL;
5823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005825
5826 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005827 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005828 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005829 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005831 }
5832 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005833 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005834 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005835 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005836 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 }
5839 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005840 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005841 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005842 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005843 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005845 }
5846 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005847 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005848 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005849 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005850 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005851 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 }
5853 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005854 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005855 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005856 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005857 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005860 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005861 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005862 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005863 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005865 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005866 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005868 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005869
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 if (curproxy == &defproxy) {
5871 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005872 err_code |= ERR_ALERT | ERR_FATAL;
5873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005874 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005875 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005876 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877
Willy Tarreaubaaee002006-06-26 02:48:02 +02005878 if (*(args[1]) == 0) {
5879 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005880 err_code |= ERR_ALERT | ERR_FATAL;
5881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005883
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005884 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005885 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5886 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5887 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005888 err_code |= ERR_ALERT | ERR_FATAL;
5889 goto out;
5890 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005891 err_code |= warnif_cond_conflicts(cond,
5892 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5893 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005894 }
5895 else if (*args[2]) {
5896 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5897 file, linenum, args[0], args[2]);
5898 err_code |= ERR_ALERT | ERR_FATAL;
5899 goto out;
5900 }
5901
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005902 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005903 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005904 wl->s = strdup(args[1]);
5905 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005906 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 }
5908 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005909 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5911 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005915
Willy Tarreauade5ec42010-01-28 19:33:49 +01005916 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005917 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005918 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005919 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005920 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005921 }
5922 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005923 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005924 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005925 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005926 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928 }
5929 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005931 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005932 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005935 }
5936 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005937 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 }
5943
Willy Tarreauade5ec42010-01-28 19:33:49 +01005944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005945 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005946 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949 }
5950 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005951 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005952 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005953 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005954 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005956 }
5957 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005958 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005959 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005960 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005961 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 }
5964 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005965 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005966
Willy Tarreaubaaee002006-06-26 02:48:02 +02005967 if (curproxy == &defproxy) {
5968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005972 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005973 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975 if (*(args[1]) == 0) {
5976 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005977 err_code |= ERR_ALERT | ERR_FATAL;
5978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005979 }
5980
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005981 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005982 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5983 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5984 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005985 err_code |= ERR_ALERT | ERR_FATAL;
5986 goto out;
5987 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005988 err_code |= warnif_cond_conflicts(cond,
5989 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5990 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005991 }
5992 else if (*args[2]) {
5993 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5994 file, linenum, args[0], args[2]);
5995 err_code |= ERR_ALERT | ERR_FATAL;
5996 goto out;
5997 }
5998
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005999 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006000 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006001 wl->s = strdup(args[1]);
6002 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006003 }
6004 else if (!strcmp(args[0], "errorloc") ||
6005 !strcmp(args[0], "errorloc302") ||
6006 !strcmp(args[0], "errorloc303")) { /* error location */
6007 int errnum, errlen;
6008 char *err;
6009
Willy Tarreau977b8e42006-12-29 14:19:17 +01006010 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006011 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006012
Willy Tarreaubaaee002006-06-26 02:48:02 +02006013 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006014 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006015 err_code |= ERR_ALERT | ERR_FATAL;
6016 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006017 }
6018
6019 errnum = atol(args[1]);
6020 if (!strcmp(args[0], "errorloc303")) {
6021 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
6022 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
6023 } else {
6024 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
6025 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
6026 }
6027
Willy Tarreau0f772532006-12-23 20:51:41 +01006028 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6029 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006030 chunk_destroy(&curproxy->errmsg[rc]);
6031 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006032 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006034 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006035
6036 if (rc >= HTTP_ERR_SIZE) {
6037 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6038 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039 free(err);
6040 }
6041 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006042 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6043 int errnum, errlen, fd;
6044 char *err;
6045 struct stat stat;
6046
6047 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006048 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006049
6050 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006051 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006054 }
6055
6056 fd = open(args[2], O_RDONLY);
6057 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6058 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6059 file, linenum, args[2], args[1]);
6060 if (fd >= 0)
6061 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006062 err_code |= ERR_ALERT | ERR_FATAL;
6063 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006064 }
6065
Willy Tarreau27a674e2009-08-17 07:23:33 +02006066 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006067 errlen = stat.st_size;
6068 } else {
6069 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006070 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006071 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006072 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006073 }
6074
6075 err = malloc(errlen); /* malloc() must succeed during parsing */
6076 errnum = read(fd, err, errlen);
6077 if (errnum != errlen) {
6078 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6079 file, linenum, args[2], args[1]);
6080 close(fd);
6081 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006084 }
6085 close(fd);
6086
6087 errnum = atol(args[1]);
6088 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6089 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006090 chunk_destroy(&curproxy->errmsg[rc]);
6091 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006092 break;
6093 }
6094 }
6095
6096 if (rc >= HTTP_ERR_SIZE) {
6097 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6098 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006099 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006100 free(err);
6101 }
6102 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006103 else if (!strcmp(args[0], "compression")) {
6104 struct comp *comp;
6105 if (curproxy->comp == NULL) {
6106 comp = calloc(1, sizeof(struct comp));
6107 curproxy->comp = comp;
6108 } else {
6109 comp = curproxy->comp;
6110 }
6111
6112 if (!strcmp(args[1], "algo")) {
6113 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006114 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006115
William Lallemand82fe75c2012-10-23 10:25:10 +02006116 cur_arg = 2;
6117 if (!*args[cur_arg]) {
6118 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6119 file, linenum, args[0]);
6120 err_code |= ERR_ALERT | ERR_FATAL;
6121 goto out;
6122 }
6123 while (*(args[cur_arg])) {
6124 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6125 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6126 file, linenum, args[0], args[cur_arg]);
6127 err_code |= ERR_ALERT | ERR_FATAL;
6128 goto out;
6129 }
William Lallemand552df672012-11-07 13:21:47 +01006130 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6131 curproxy->comp->algos->end(&ctx);
6132 } else {
6133 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6134 file, linenum, args[0], args[cur_arg]);
6135 err_code |= ERR_ALERT | ERR_FATAL;
6136 goto out;
6137 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006138 cur_arg ++;
6139 continue;
6140 }
6141 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006142 else if (!strcmp(args[1], "offload")) {
6143 comp->offload = 1;
6144 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006145 else if (!strcmp(args[1], "type")) {
6146 int cur_arg;
6147 cur_arg = 2;
6148 if (!*args[cur_arg]) {
6149 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6150 file, linenum, args[0]);
6151 err_code |= ERR_ALERT | ERR_FATAL;
6152 goto out;
6153 }
6154 while (*(args[cur_arg])) {
6155 comp_append_type(comp, args[cur_arg]);
6156 cur_arg ++;
6157 continue;
6158 }
6159 }
6160 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006161 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006162 file, linenum, args[0]);
6163 err_code |= ERR_ALERT | ERR_FATAL;
6164 goto out;
6165 }
6166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006168 struct cfg_kw_list *kwl;
6169 int index;
6170
6171 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6172 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6173 if (kwl->kw[index].section != CFG_LISTEN)
6174 continue;
6175 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6176 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006177 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006178 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006179 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006180 err_code |= ERR_ALERT | ERR_FATAL;
6181 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006182 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006183 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006184 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006185 err_code |= ERR_WARN;
6186 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006187 }
Willy Tarreau93893792009-07-23 13:19:11 +02006188 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006189 }
6190 }
6191 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006192
Willy Tarreau6daf3432008-01-22 16:44:08 +01006193 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006194 err_code |= ERR_ALERT | ERR_FATAL;
6195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196 }
Willy Tarreau93893792009-07-23 13:19:11 +02006197 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006198 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006199 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200}
6201
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006202int
6203cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6204{
6205
6206 int err_code = 0;
6207 const char *err;
6208
6209 if (!strcmp(args[0], "userlist")) { /* new userlist */
6210 struct userlist *newul;
6211
6212 if (!*args[1]) {
6213 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6214 file, linenum, args[0]);
6215 err_code |= ERR_ALERT | ERR_FATAL;
6216 goto out;
6217 }
6218
6219 err = invalid_char(args[1]);
6220 if (err) {
6221 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6222 file, linenum, *err, args[0], args[1]);
6223 err_code |= ERR_ALERT | ERR_FATAL;
6224 goto out;
6225 }
6226
6227 for (newul = userlist; newul; newul = newul->next)
6228 if (!strcmp(newul->name, args[1])) {
6229 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6230 file, linenum, args[1]);
6231 err_code |= ERR_WARN;
6232 goto out;
6233 }
6234
6235 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6236 if (!newul) {
6237 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6238 err_code |= ERR_ALERT | ERR_ABORT;
6239 goto out;
6240 }
6241
6242 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6243 newul->name = strdup(args[1]);
6244
6245 if (!newul->groupusers | !newul->name) {
6246 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6247 err_code |= ERR_ALERT | ERR_ABORT;
6248 goto out;
6249 }
6250
6251 newul->next = userlist;
6252 userlist = newul;
6253
6254 } else if (!strcmp(args[0], "group")) { /* new group */
6255 int cur_arg, i;
6256 const char *err;
6257
6258 if (!*args[1]) {
6259 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6260 file, linenum, args[0]);
6261 err_code |= ERR_ALERT | ERR_FATAL;
6262 goto out;
6263 }
6264
6265 err = invalid_char(args[1]);
6266 if (err) {
6267 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6268 file, linenum, *err, args[0], args[1]);
6269 err_code |= ERR_ALERT | ERR_FATAL;
6270 goto out;
6271 }
6272
6273 for(i = 0; i < userlist->grpcnt; i++)
6274 if (!strcmp(userlist->groups[i], args[1])) {
6275 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6276 file, linenum, args[1], userlist->name);
6277 err_code |= ERR_ALERT;
6278 goto out;
6279 }
6280
6281 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6282 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6283 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6284 err_code |= ERR_ALERT | ERR_FATAL;
6285 goto out;
6286 }
6287
6288 cur_arg = 2;
6289
6290 while (*args[cur_arg]) {
6291 if (!strcmp(args[cur_arg], "users")) {
6292 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6293 cur_arg += 2;
6294 continue;
6295 } else {
6296 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6297 file, linenum, args[0]);
6298 err_code |= ERR_ALERT | ERR_FATAL;
6299 goto out;
6300 }
6301 }
6302
6303 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6304 } else if (!strcmp(args[0], "user")) { /* new user */
6305 struct auth_users *newuser;
6306 int cur_arg;
6307
6308 if (!*args[1]) {
6309 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6310 file, linenum, args[0]);
6311 err_code |= ERR_ALERT | ERR_FATAL;
6312 goto out;
6313 }
6314
6315 for (newuser = userlist->users; newuser; newuser = newuser->next)
6316 if (!strcmp(newuser->user, args[1])) {
6317 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6318 file, linenum, args[1], userlist->name);
6319 err_code |= ERR_ALERT;
6320 goto out;
6321 }
6322
6323 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6324 if (!newuser) {
6325 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6326 err_code |= ERR_ALERT | ERR_ABORT;
6327 goto out;
6328 }
6329
6330 newuser->user = strdup(args[1]);
6331
6332 newuser->next = userlist->users;
6333 userlist->users = newuser;
6334
6335 cur_arg = 2;
6336
6337 while (*args[cur_arg]) {
6338 if (!strcmp(args[cur_arg], "password")) {
6339#ifndef CONFIG_HAP_CRYPT
6340 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6341 file, linenum);
6342 err_code |= ERR_ALERT;
6343#endif
6344 newuser->pass = strdup(args[cur_arg + 1]);
6345 cur_arg += 2;
6346 continue;
6347 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6348 newuser->pass = strdup(args[cur_arg + 1]);
6349 newuser->flags |= AU_O_INSECURE;
6350 cur_arg += 2;
6351 continue;
6352 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006353 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006354 cur_arg += 2;
6355 continue;
6356 } else {
6357 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6358 file, linenum, args[0]);
6359 err_code |= ERR_ALERT | ERR_FATAL;
6360 goto out;
6361 }
6362 }
6363 } else {
6364 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6365 err_code |= ERR_ALERT | ERR_FATAL;
6366 }
6367
6368out:
6369 return err_code;
6370}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006371
6372/*
6373 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006374 * 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.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006381 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006382int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006384 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385 FILE *f;
6386 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006388 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006389
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 if ((f=fopen(file,"r")) == NULL)
6391 return -1;
6392
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006393 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006394 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006395 char *end;
6396 char *args[MAX_LINE_ARGS + 1];
6397 char *line = thisline;
6398
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 linenum++;
6400
6401 end = line + strlen(line);
6402
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006403 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6404 /* Check if we reached the limit and the last char is not \n.
6405 * Watch out for the last line without the terminating '\n'!
6406 */
6407 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006408 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006409 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006410 }
6411
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006413 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 line++;
6415
6416 arg = 0;
6417 args[arg] = line;
6418
6419 while (*line && arg < MAX_LINE_ARGS) {
6420 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6421 * C equivalent value. Other combinations left unchanged (eg: \1).
6422 */
6423 if (*line == '\\') {
6424 int skip = 0;
6425 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6426 *line = line[1];
6427 skip = 1;
6428 }
6429 else if (line[1] == 'r') {
6430 *line = '\r';
6431 skip = 1;
6432 }
6433 else if (line[1] == 'n') {
6434 *line = '\n';
6435 skip = 1;
6436 }
6437 else if (line[1] == 't') {
6438 *line = '\t';
6439 skip = 1;
6440 }
6441 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006442 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006443 unsigned char hex1, hex2;
6444 hex1 = toupper(line[2]) - '0';
6445 hex2 = toupper(line[3]) - '0';
6446 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6447 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6448 *line = (hex1<<4) + hex2;
6449 skip = 3;
6450 }
6451 else {
6452 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006453 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 }
6455 }
6456 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006457 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006458 end -= skip;
6459 }
6460 line++;
6461 }
6462 else if (*line == '#' || *line == '\n' || *line == '\r') {
6463 /* end of string, end of loop */
6464 *line = 0;
6465 break;
6466 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006467 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006468 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006469 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006470 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 line++;
6472 args[++arg] = line;
6473 }
6474 else {
6475 line++;
6476 }
6477 }
6478
6479 /* empty line */
6480 if (!**args)
6481 continue;
6482
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006483 if (*line) {
6484 /* we had to stop due to too many args.
6485 * Let's terminate the string, print the offending part then cut the
6486 * last arg.
6487 */
6488 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6489 line++;
6490 *line = '\0';
6491
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006492 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006493 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006494 err_code |= ERR_ALERT | ERR_FATAL;
6495 args[arg] = line;
6496 }
6497
Willy Tarreau540abe42007-05-02 20:50:16 +02006498 /* zero out remaining args and ensure that at least one entry
6499 * is zeroed out.
6500 */
6501 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006502 args[arg] = line;
6503 }
6504
Willy Tarreau3842f002009-06-14 11:39:52 +02006505 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006506 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006507 char *tmp;
6508
Willy Tarreau3842f002009-06-14 11:39:52 +02006509 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006510 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006511 for (arg=0; *args[arg+1]; arg++)
6512 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006513 *tmp = '\0'; // fix the next arg to \0
6514 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006515 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006516 else if (!strcmp(args[0], "default")) {
6517 kwm = KWM_DEF;
6518 for (arg=0; *args[arg+1]; arg++)
6519 args[arg] = args[arg+1]; // shift args after inversion
6520 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006521
William Lallemand0f99e342011-10-12 17:50:54 +02006522 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6523 strcmp(args[0], "log") != 0) {
6524 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006525 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006526 }
6527
Willy Tarreau977b8e42006-12-29 14:19:17 +01006528 if (!strcmp(args[0], "listen") ||
6529 !strcmp(args[0], "frontend") ||
6530 !strcmp(args[0], "backend") ||
6531 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006532 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006533 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006534 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006535 cursection = strdup(args[0]);
6536 }
6537 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006539 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006540 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006541 }
6542 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006543 confsect = CFG_USERLIST;
6544 free(cursection);
6545 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006546 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006547 else if (!strcmp(args[0], "peers")) {
6548 confsect = CFG_PEERS;
6549 free(cursection);
6550 cursection = strdup(args[0]);
6551 }
6552
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553 /* else it's a section keyword */
6554
6555 switch (confsect) {
6556 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006557 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006558 break;
6559 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006560 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006562 case CFG_USERLIST:
6563 err_code |= cfg_parse_users(file, linenum, args, kwm);
6564 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006565 case CFG_PEERS:
6566 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6567 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006569 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006570 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006571 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006572
6573 if (err_code & ERR_ABORT)
6574 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006575 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006576 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006577 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006579 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006580}
6581
Willy Tarreaubb925012009-07-23 13:36:36 +02006582/*
6583 * Returns the error code, 0 if OK, or any combination of :
6584 * - ERR_ABORT: must abort ASAP
6585 * - ERR_FATAL: we can continue parsing but not start the service
6586 * - ERR_WARN: a warning has been emitted
6587 * - ERR_ALERT: an alert has been emitted
6588 * Only the two first ones can stop processing, the two others are just
6589 * indicators.
6590 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006591int check_config_validity()
6592{
6593 int cfgerr = 0;
6594 struct proxy *curproxy = NULL;
6595 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006596 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006597 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006598 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006599 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006601 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602 /*
6603 * Now, check for the integrity of all that we have collected.
6604 */
6605
6606 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006607 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006608
Willy Tarreau193b8c62012-11-22 00:17:38 +01006609 if (!global.tune.max_http_hdr)
6610 global.tune.max_http_hdr = MAX_HTTP_HDR;
6611
6612 if (!global.tune.cookie_len)
6613 global.tune.cookie_len = CAPTURE_LEN;
6614
6615 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6616
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006617 /* first, we will invert the proxy list order */
6618 curproxy = NULL;
6619 while (proxy) {
6620 struct proxy *next;
6621
6622 next = proxy->next;
6623 proxy->next = curproxy;
6624 curproxy = proxy;
6625 if (!next)
6626 break;
6627 proxy = next;
6628 }
6629
Willy Tarreaubaaee002006-06-26 02:48:02 +02006630 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006631 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006632 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006633 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006634 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006635 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006636 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006637 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006638
Willy Tarreau050536d2012-10-04 08:47:34 +02006639 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006640 /* proxy ID not set, use automatic numbering with first
6641 * spare entry starting with next_pxid.
6642 */
6643 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6644 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6645 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006646 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006647 next_pxid++;
6648
Willy Tarreau55ea7572007-06-17 19:56:27 +02006649
Willy Tarreaubaaee002006-06-26 02:48:02 +02006650 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006651 /* ensure we don't keep listeners uselessly bound */
6652 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006653 curproxy = curproxy->next;
6654 continue;
6655 }
6656
Willy Tarreau16a21472012-11-19 12:39:59 +01006657 /* number of processes this proxy is bound to */
6658 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6659
Willy Tarreauff01a212009-03-15 13:46:16 +01006660 switch (curproxy->mode) {
6661 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006662 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006663 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006664 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6665 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006666 cfgerr++;
6667 }
6668
6669 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006670 Warning("config : servers will be ignored for %s '%s'.\n",
6671 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006672 break;
6673
6674 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006675 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006676 break;
6677
6678 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006679 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006680 break;
6681 }
6682
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006683 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006684 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006685 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006686 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6687 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006688 cfgerr++;
6689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006690#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006691 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006692 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6693 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006694 cfgerr++;
6695 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006696#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006697 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006698 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6699 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006700 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006701 }
6702 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006703 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006704 /* If no LB algo is set in a backend, and we're not in
6705 * transparent mode, dispatch mode nor proxy mode, we
6706 * want to use balance roundrobin by default.
6707 */
6708 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6709 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006710 }
6711 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006712
Willy Tarreau1620ec32011-08-06 17:05:02 +02006713 if (curproxy->options & PR_O_DISPATCH)
6714 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6715 else if (curproxy->options & PR_O_HTTP_PROXY)
6716 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6717 else if (curproxy->options & PR_O_TRANSP)
6718 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006719
Willy Tarreau1620ec32011-08-06 17:05:02 +02006720 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6721 if (curproxy->options & PR_O_DISABLE404) {
6722 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6723 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6724 err_code |= ERR_WARN;
6725 curproxy->options &= ~PR_O_DISABLE404;
6726 }
6727 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6728 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6729 "send-state", proxy_type_str(curproxy), curproxy->id);
6730 err_code |= ERR_WARN;
6731 curproxy->options &= ~PR_O2_CHK_SNDST;
6732 }
Willy Tarreauef781042010-01-27 11:53:01 +01006733 }
6734
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006735 /* if a default backend was specified, let's find it */
6736 if (curproxy->defbe.name) {
6737 struct proxy *target;
6738
Alex Williams96532db2009-11-01 21:27:13 -05006739 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006740 if (!target) {
6741 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6742 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006743 cfgerr++;
6744 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006745 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6746 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006747 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006748 } else {
6749 free(curproxy->defbe.name);
6750 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006751 /* we force the backend to be present on at least all of
6752 * the frontend's processes.
6753 */
6754 target->bind_proc = curproxy->bind_proc ?
6755 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006756
6757 /* Emit a warning if this proxy also has some servers */
6758 if (curproxy->srv) {
6759 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6760 curproxy->id);
6761 err_code |= ERR_WARN;
6762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006763 }
6764 }
6765
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006766 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006767 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6768 /* map jump target for ACT_SETBE in req_rep chain */
6769 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006770 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006771 struct proxy *target;
6772
Willy Tarreaua496b602006-12-17 23:15:24 +01006773 if (exp->action != ACT_SETBE)
6774 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006775
Alex Williams96532db2009-11-01 21:27:13 -05006776 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006777 if (!target) {
6778 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6779 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006780 cfgerr++;
6781 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006782 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6783 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006784 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006785 } else {
6786 free((void *)exp->replace);
6787 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006788 /* we force the backend to be present on at least all of
6789 * the frontend's processes.
6790 */
6791 target->bind_proc = curproxy->bind_proc ?
6792 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006793 }
6794 }
6795 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006796
6797 /* find the target proxy for 'use_backend' rules */
6798 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006799 struct proxy *target;
6800
Alex Williams96532db2009-11-01 21:27:13 -05006801 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006802
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006803 if (!target) {
6804 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6805 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006806 cfgerr++;
6807 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006808 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6809 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006810 cfgerr++;
6811 } else {
6812 free((void *)rule->be.name);
6813 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006814 /* we force the backend to be present on at least all of
6815 * the frontend's processes.
6816 */
6817 target->bind_proc = curproxy->bind_proc ?
6818 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006819 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006820 }
6821
6822 /* find the target proxy for 'use_backend' rules */
6823 list_for_each_entry(srule, &curproxy->server_rules, list) {
6824 struct server *target = findserver(curproxy, srule->srv.name);
6825
6826 if (!target) {
6827 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6828 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6829 cfgerr++;
6830 continue;
6831 }
6832 free((void *)srule->srv.name);
6833 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006834 }
6835
Emeric Brunb982a3d2010-01-04 15:45:53 +01006836 /* find the target table for 'stick' rules */
6837 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6838 struct proxy *target;
6839
Emeric Brun1d33b292010-01-04 15:47:17 +01006840 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6841 if (mrule->flags & STK_IS_STORE)
6842 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6843
Emeric Brunb982a3d2010-01-04 15:45:53 +01006844 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006845 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006846 else
6847 target = curproxy;
6848
6849 if (!target) {
6850 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6851 curproxy->id, mrule->table.name);
6852 cfgerr++;
6853 }
6854 else if (target->table.size == 0) {
6855 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6856 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6857 cfgerr++;
6858 }
Willy Tarreau12785782012-04-27 21:37:17 +02006859 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6860 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006861 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6862 cfgerr++;
6863 }
6864 else {
6865 free((void *)mrule->table.name);
6866 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006867 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006868 }
6869 }
6870
6871 /* find the target table for 'store response' rules */
6872 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6873 struct proxy *target;
6874
Emeric Brun1d33b292010-01-04 15:47:17 +01006875 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6876
Emeric Brunb982a3d2010-01-04 15:45:53 +01006877 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006878 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006879 else
6880 target = curproxy;
6881
6882 if (!target) {
6883 Alert("Proxy '%s': unable to find store table '%s'.\n",
6884 curproxy->id, mrule->table.name);
6885 cfgerr++;
6886 }
6887 else if (target->table.size == 0) {
6888 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6889 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6890 cfgerr++;
6891 }
Willy Tarreau12785782012-04-27 21:37:17 +02006892 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6893 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006894 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6895 cfgerr++;
6896 }
6897 else {
6898 free((void *)mrule->table.name);
6899 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006900 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006901 }
6902 }
6903
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006904 /* find the target table for 'tcp-request' layer 4 rules */
6905 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6906 struct proxy *target;
6907
Willy Tarreaub4c84932013-07-23 19:15:30 +02006908 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006909 continue;
6910
6911 if (trule->act_prm.trk_ctr.table.n)
6912 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6913 else
6914 target = curproxy;
6915
6916 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006917 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6918 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006919 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006920 cfgerr++;
6921 }
6922 else if (target->table.size == 0) {
6923 Alert("Proxy '%s': table '%s' used but not configured.\n",
6924 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6925 cfgerr++;
6926 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006927 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6928 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6929 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 +01006930 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006931 cfgerr++;
6932 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006933 else {
6934 free(trule->act_prm.trk_ctr.table.n);
6935 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006936 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006937 * to pass a list of counters to track and allocate them right here using
6938 * stktable_alloc_data_type().
6939 */
6940 }
6941 }
6942
Willy Tarreaud1f96522010-08-03 19:34:32 +02006943 /* find the target table for 'tcp-request' layer 6 rules */
6944 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6945 struct proxy *target;
6946
Willy Tarreaub4c84932013-07-23 19:15:30 +02006947 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006948 continue;
6949
6950 if (trule->act_prm.trk_ctr.table.n)
6951 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6952 else
6953 target = curproxy;
6954
6955 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006956 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6957 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006958 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006959 cfgerr++;
6960 }
6961 else if (target->table.size == 0) {
6962 Alert("Proxy '%s': table '%s' used but not configured.\n",
6963 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6964 cfgerr++;
6965 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006966 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6967 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6968 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 +01006969 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006970 cfgerr++;
6971 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006972 else {
6973 free(trule->act_prm.trk_ctr.table.n);
6974 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006975 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006976 * to pass a list of counters to track and allocate them right here using
6977 * stktable_alloc_data_type().
6978 */
6979 }
6980 }
6981
Emeric Brun32da3c42010-09-23 18:39:19 +02006982 if (curproxy->table.peers.name) {
6983 struct peers *curpeers = peers;
6984
6985 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6986 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6987 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006988 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006989 break;
6990 }
6991 }
6992
6993 if (!curpeers) {
6994 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6995 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006996 free((void *)curproxy->table.peers.name);
6997 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006998 cfgerr++;
6999 }
7000 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007001 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7002 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007003 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007004 cfgerr++;
7005 }
7006 }
7007
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007008 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007009 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007010 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7011 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7012 "proxy", curproxy->id);
7013 cfgerr++;
7014 goto out_uri_auth_compat;
7015 }
7016
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007017 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007018 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007019 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007020 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007021
Willy Tarreau95fa4692010-02-01 13:05:50 +01007022 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7023 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007024
7025 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007026 uri_auth_compat_req[i++] = "realm";
7027 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7028 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007029
Willy Tarreau95fa4692010-02-01 13:05:50 +01007030 uri_auth_compat_req[i++] = "unless";
7031 uri_auth_compat_req[i++] = "{";
7032 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7033 uri_auth_compat_req[i++] = "}";
7034 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007035
Willy Tarreauff011f22011-01-06 17:51:27 +01007036 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7037 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007038 cfgerr++;
7039 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007040 }
7041
Willy Tarreauff011f22011-01-06 17:51:27 +01007042 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007043
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007044 if (curproxy->uri_auth->auth_realm) {
7045 free(curproxy->uri_auth->auth_realm);
7046 curproxy->uri_auth->auth_realm = NULL;
7047 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007048
7049 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007050 }
7051out_uri_auth_compat:
7052
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007053 /* compile the log format */
7054 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007055 if (curproxy->conf.logformat_string != default_http_log_format &&
7056 curproxy->conf.logformat_string != default_tcp_log_format &&
7057 curproxy->conf.logformat_string != clf_http_log_format)
7058 free(curproxy->conf.logformat_string);
7059 curproxy->conf.logformat_string = NULL;
7060 free(curproxy->conf.lfs_file);
7061 curproxy->conf.lfs_file = NULL;
7062 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007063 }
7064
Willy Tarreau62a61232013-04-12 18:13:46 +02007065 if (curproxy->conf.logformat_string) {
7066 curproxy->conf.args.ctx = ARGC_LOG;
7067 curproxy->conf.args.file = curproxy->conf.lfs_file;
7068 curproxy->conf.args.line = curproxy->conf.lfs_line;
7069 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007070 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02007071 curproxy->conf.args.file = NULL;
7072 curproxy->conf.args.line = 0;
7073 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007074
Willy Tarreau62a61232013-04-12 18:13:46 +02007075 if (curproxy->conf.uniqueid_format_string) {
7076 curproxy->conf.args.ctx = ARGC_UIF;
7077 curproxy->conf.args.file = curproxy->conf.uif_file;
7078 curproxy->conf.args.line = curproxy->conf.uif_line;
7079 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007080 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02007081 curproxy->conf.args.file = NULL;
7082 curproxy->conf.args.line = 0;
7083 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007084
7085 /* only now we can check if some args remain unresolved */
7086 cfgerr += smp_resolve_args(curproxy);
7087 if (!cfgerr)
7088 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007089
Willy Tarreau2738a142006-07-08 17:28:09 +02007090 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007091 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007092 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007093 (!curproxy->timeout.connect ||
7094 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007095 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007096 " | While not properly invalid, you will certainly encounter various problems\n"
7097 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007098 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007099 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007100 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007101 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007102
Willy Tarreau1fa31262007-12-03 00:36:16 +01007103 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7104 * We must still support older configurations, so let's find out whether those
7105 * parameters have been set or must be copied from contimeouts.
7106 */
7107 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007108 if (!curproxy->timeout.tarpit ||
7109 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007110 /* tarpit timeout not set. We search in the following order:
7111 * default.tarpit, curr.connect, default.connect.
7112 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007113 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007114 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007115 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007116 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007117 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007118 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007119 }
7120 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007121 (!curproxy->timeout.queue ||
7122 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007123 /* queue timeout not set. We search in the following order:
7124 * default.queue, curr.connect, default.connect.
7125 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007126 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007127 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007128 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007129 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007130 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007131 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007132 }
7133 }
7134
Willy Tarreau1620ec32011-08-06 17:05:02 +02007135 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007136 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7137 curproxy->check_req = (char *)malloc(curproxy->check_len);
7138 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007139 }
7140
Willy Tarreau193b8c62012-11-22 00:17:38 +01007141 /* ensure that cookie capture length is not too large */
7142 if (curproxy->capture_len >= global.tune.cookie_len) {
7143 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7144 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7145 err_code |= ERR_WARN;
7146 curproxy->capture_len = global.tune.cookie_len - 1;
7147 }
7148
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007149 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007150 if (curproxy->nb_req_cap) {
7151 if (curproxy->mode == PR_MODE_HTTP) {
7152 curproxy->req_cap_pool = create_pool("ptrcap",
7153 curproxy->nb_req_cap * sizeof(char *),
7154 MEM_F_SHARED);
7155 } else {
7156 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7157 proxy_type_str(curproxy), curproxy->id);
7158 err_code |= ERR_WARN;
7159 curproxy->to_log &= ~LW_REQHDR;
7160 curproxy->nb_req_cap = 0;
7161 }
7162 }
7163
7164 if (curproxy->nb_rsp_cap) {
7165 if (curproxy->mode == PR_MODE_HTTP) {
7166 curproxy->rsp_cap_pool = create_pool("ptrcap",
7167 curproxy->nb_rsp_cap * sizeof(char *),
7168 MEM_F_SHARED);
7169 } else {
7170 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7171 proxy_type_str(curproxy), curproxy->id);
7172 err_code |= ERR_WARN;
7173 curproxy->to_log &= ~LW_REQHDR;
7174 curproxy->nb_rsp_cap = 0;
7175 }
7176 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007177
Willy Tarreaubaaee002006-06-26 02:48:02 +02007178 /* first, we will invert the servers list order */
7179 newsrv = NULL;
7180 while (curproxy->srv) {
7181 struct server *next;
7182
7183 next = curproxy->srv->next;
7184 curproxy->srv->next = newsrv;
7185 newsrv = curproxy->srv;
7186 if (!next)
7187 break;
7188 curproxy->srv = next;
7189 }
7190
Willy Tarreau17edc812014-01-03 12:14:34 +01007191 /* Check that no server name conflicts. This causes trouble in the stats.
7192 * We only emit a warning for the first conflict affecting each server,
7193 * in order to avoid combinatory explosion if all servers have the same
7194 * name. We do that only for servers which do not have an explicit ID,
7195 * because these IDs were made also for distinguishing them and we don't
7196 * want to annoy people who correctly manage them.
7197 */
7198 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7199 struct server *other_srv;
7200
7201 if (newsrv->puid)
7202 continue;
7203
7204 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7205 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7206 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7207 newsrv->conf.file, newsrv->conf.line,
7208 proxy_type_str(curproxy), curproxy->id,
7209 newsrv->id, other_srv->conf.line);
7210 break;
7211 }
7212 }
7213 }
7214
Willy Tarreaudd701652010-05-25 23:03:02 +02007215 /* assign automatic UIDs to servers which don't have one yet */
7216 next_id = 1;
7217 newsrv = curproxy->srv;
7218 while (newsrv != NULL) {
7219 if (!newsrv->puid) {
7220 /* server ID not set, use automatic numbering with first
7221 * spare entry starting with next_svid.
7222 */
7223 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7224 newsrv->conf.id.key = newsrv->puid = next_id;
7225 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7226 }
7227 next_id++;
7228 newsrv = newsrv->next;
7229 }
7230
Willy Tarreau20697042007-11-15 23:26:18 +01007231 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007232 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007233
Willy Tarreau62c3be22012-01-20 13:12:32 +01007234 /*
7235 * If this server supports a maxconn parameter, it needs a dedicated
7236 * tasks to fill the emptied slots when a connection leaves.
7237 * Also, resolve deferred tracking dependency if needed.
7238 */
7239 newsrv = curproxy->srv;
7240 while (newsrv != NULL) {
7241 if (newsrv->minconn > newsrv->maxconn) {
7242 /* Only 'minconn' was specified, or it was higher than or equal
7243 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7244 * this will avoid further useless expensive computations.
7245 */
7246 newsrv->maxconn = newsrv->minconn;
7247 } else if (newsrv->maxconn && !newsrv->minconn) {
7248 /* minconn was not specified, so we set it to maxconn */
7249 newsrv->minconn = newsrv->maxconn;
7250 }
7251
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007252#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007253 if (newsrv->use_ssl || newsrv->check.use_ssl)
7254 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007255#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007256
Willy Tarreau2f075e92013-12-03 11:11:34 +01007257 /* set the check type on the server */
7258 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7259
Willy Tarreau62c3be22012-01-20 13:12:32 +01007260 if (newsrv->trackit) {
7261 struct proxy *px;
7262 struct server *srv;
7263 char *pname, *sname;
7264
7265 pname = newsrv->trackit;
7266 sname = strrchr(pname, '/');
7267
7268 if (sname)
7269 *sname++ = '\0';
7270 else {
7271 sname = pname;
7272 pname = NULL;
7273 }
7274
7275 if (pname) {
7276 px = findproxy(pname, PR_CAP_BE);
7277 if (!px) {
7278 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7279 proxy_type_str(curproxy), curproxy->id,
7280 newsrv->id, pname);
7281 cfgerr++;
7282 goto next_srv;
7283 }
7284 } else
7285 px = curproxy;
7286
7287 srv = findserver(px, sname);
7288 if (!srv) {
7289 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7290 proxy_type_str(curproxy), curproxy->id,
7291 newsrv->id, sname);
7292 cfgerr++;
7293 goto next_srv;
7294 }
7295
Willy Tarreauff5ae352013-12-11 20:36:34 +01007296 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007297 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7298 "tracking as it does not have checks enabled.\n",
7299 proxy_type_str(curproxy), curproxy->id,
7300 newsrv->id, px->id, srv->id);
7301 cfgerr++;
7302 goto next_srv;
7303 }
7304
7305 if (curproxy != px &&
7306 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7307 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7308 "tracking: disable-on-404 option inconsistency.\n",
7309 proxy_type_str(curproxy), curproxy->id,
7310 newsrv->id, px->id, srv->id);
7311 cfgerr++;
7312 goto next_srv;
7313 }
7314
7315 /* if the other server is forced disabled, we have to do the same here */
7316 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007317 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007318 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007319 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007320 }
7321
7322 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007323 newsrv->tracknext = srv->trackers;
7324 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007325
7326 free(newsrv->trackit);
7327 newsrv->trackit = NULL;
7328 }
7329 next_srv:
7330 newsrv = newsrv->next;
7331 }
7332
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007333 /* We have to initialize the server lookup mechanism depending
7334 * on what LB algorithm was choosen.
7335 */
7336
7337 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7338 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7339 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007340 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7341 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7342 init_server_map(curproxy);
7343 } else {
7344 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7345 fwrr_init_server_groups(curproxy);
7346 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007347 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007348
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007349 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007350 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7351 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7352 fwlc_init_server_tree(curproxy);
7353 } else {
7354 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7355 fas_init_server_tree(curproxy);
7356 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007357 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007358
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007359 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007360 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7361 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7362 chash_init_server_tree(curproxy);
7363 } else {
7364 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7365 init_server_map(curproxy);
7366 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007367 break;
7368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007369
7370 if (curproxy->options & PR_O_LOGASAP)
7371 curproxy->to_log &= ~LW_BYTES;
7372
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007373 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007374 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007375 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7376 proxy_type_str(curproxy), curproxy->id);
7377 err_code |= ERR_WARN;
7378 }
7379
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007380 if (curproxy->mode != PR_MODE_HTTP) {
7381 int optnum;
7382
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007383 if (curproxy->uri_auth) {
7384 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7385 proxy_type_str(curproxy), curproxy->id);
7386 err_code |= ERR_WARN;
7387 curproxy->uri_auth = NULL;
7388 }
7389
Willy Tarreau87cf5142011-08-19 22:57:24 +02007390 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007391 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7392 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7393 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007394 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007395 }
7396
7397 if (curproxy->options & PR_O_ORGTO) {
7398 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7399 "originalto", proxy_type_str(curproxy), curproxy->id);
7400 err_code |= ERR_WARN;
7401 curproxy->options &= ~PR_O_ORGTO;
7402 }
7403
7404 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7405 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7406 (curproxy->cap & cfg_opts[optnum].cap) &&
7407 (curproxy->options & cfg_opts[optnum].val)) {
7408 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7409 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7410 err_code |= ERR_WARN;
7411 curproxy->options &= ~cfg_opts[optnum].val;
7412 }
7413 }
7414
7415 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7416 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7417 (curproxy->cap & cfg_opts2[optnum].cap) &&
7418 (curproxy->options2 & cfg_opts2[optnum].val)) {
7419 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7420 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7421 err_code |= ERR_WARN;
7422 curproxy->options2 &= ~cfg_opts2[optnum].val;
7423 }
7424 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007425
Pieter Baauwd551fb52013-05-08 22:49:23 +02007426#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007427 if (curproxy->conn_src.bind_hdr_occ) {
7428 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007429 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007430 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007431 err_code |= ERR_WARN;
7432 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007433#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007434 }
7435
Willy Tarreaubaaee002006-06-26 02:48:02 +02007436 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007437 * ensure that we're not cross-dressing a TCP server into HTTP.
7438 */
7439 newsrv = curproxy->srv;
7440 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007441 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007442 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7443 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007444 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007445 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007446
Willy Tarreau0cec3312011-10-31 13:49:26 +01007447 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7448 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7449 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7450 err_code |= ERR_WARN;
7451 }
7452
Willy Tarreau82ffa392013-08-13 17:19:08 +02007453 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7454 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7455 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7456 err_code |= ERR_WARN;
7457 }
7458
Pieter Baauwd551fb52013-05-08 22:49:23 +02007459#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007460 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7461 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007462 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 +01007463 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007464 err_code |= ERR_WARN;
7465 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007466#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007467 newsrv = newsrv->next;
7468 }
7469
Willy Tarreauc1a21672009-08-16 22:37:44 +02007470 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007471 if (!curproxy->accept)
7472 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007473
Willy Tarreauc1a21672009-08-16 22:37:44 +02007474 if (curproxy->tcp_req.inspect_delay ||
7475 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007476 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007477
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007478 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007479 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007480 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007481 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007482
7483 /* both TCP and HTTP must check switching rules */
7484 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7485 }
7486
7487 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007488 if (curproxy->tcp_req.inspect_delay ||
7489 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7490 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7491
Emeric Brun97679e72010-09-23 17:56:44 +02007492 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7493 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7494
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007495 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007496 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007497 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007498 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007499
7500 /* If the backend does requires RDP cookie persistence, we have to
7501 * enable the corresponding analyser.
7502 */
7503 if (curproxy->options2 & PR_O2_RDPC_PRST)
7504 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7505 }
7506
Emeric Brunc52962f2012-11-15 18:28:02 +01007507#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007508 /* Configure SSL for each bind line.
7509 * Note: if configuration fails at some point, the ->ctx member
7510 * remains NULL so that listeners can later detach.
7511 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007512 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007513 if (!bind_conf->is_ssl) {
7514 if (bind_conf->default_ctx) {
7515 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7516 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7517 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007518 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007519 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007520 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007521 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007522 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007523 cfgerr++;
7524 continue;
7525 }
7526
Emeric Brun4b3091e2012-09-24 15:48:52 +02007527 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007528 Alert("Unable to allocate SSL session cache.\n");
7529 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007530 continue;
7531 }
7532
Emeric Brunfc0421f2012-09-07 17:30:07 +02007533 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007534 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007535 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007536#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007537
Willy Tarreaue6b98942007-10-29 01:09:36 +01007538 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007539 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007540 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007541 if (!listener->luid) {
7542 /* listener ID not set, use automatic numbering with first
7543 * spare entry starting with next_luid.
7544 */
7545 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7546 listener->conf.id.key = listener->luid = next_id;
7547 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007548 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007549 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007550
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007551 /* enable separate counters */
7552 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7553 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007554 if (!listener->name)
7555 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007556 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007557
Willy Tarreaue6b98942007-10-29 01:09:36 +01007558 if (curproxy->options & PR_O_TCP_NOLING)
7559 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007560 if (!listener->maxconn)
7561 listener->maxconn = curproxy->maxconn;
7562 if (!listener->backlog)
7563 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007564 if (!listener->maxaccept)
7565 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7566
7567 /* we want to have an optimal behaviour on single process mode to
7568 * maximize the work at once, but in multi-process we want to keep
7569 * some fairness between processes, so we target half of the max
7570 * number of events to be balanced over all the processes the proxy
7571 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7572 * used to disable the limit.
7573 */
7574 if (listener->maxaccept > 0) {
7575 if (nbproc > 1)
7576 listener->maxaccept = (listener->maxaccept + 1) / 2;
7577 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7578 }
7579
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007580 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007581 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007582 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007583 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007584
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007585 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7586 listener->options |= LI_O_TCP_RULES;
7587
Willy Tarreaude3041d2010-05-31 10:56:17 +02007588 if (curproxy->mon_mask.s_addr)
7589 listener->options |= LI_O_CHK_MONNET;
7590
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007591 /* smart accept mode is automatic in HTTP mode */
7592 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007593 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007594 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7595 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007596 }
7597
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007598 /* Release unused SSL configs */
7599 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7600 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007601 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007602#ifdef USE_OPENSSL
7603 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007604 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007605 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007606 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007607 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007608#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007609 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007610
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007611 /* Check multi-process mode compatibility for the current proxy */
7612 if (global.nbproc > 1) {
7613 int nbproc = 0;
7614 if (curproxy->bind_proc) {
7615 int proc;
7616 for (proc = 0; proc < global.nbproc; proc++) {
7617 if (curproxy->bind_proc & (1 << proc)) {
7618 nbproc++;
7619 }
7620 }
7621 } else {
7622 nbproc = global.nbproc;
7623 }
7624 if (curproxy->table.peers.name) {
7625 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7626 curproxy->id);
7627 cfgerr++;
7628 }
7629 if (nbproc > 1) {
7630 if (curproxy->uri_auth) {
7631 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7632 curproxy->id);
7633 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7634 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7635 curproxy->id);
7636 }
7637 }
7638 if (curproxy->appsession_name) {
7639 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7640 curproxy->id);
7641 }
7642 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7643 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7644 curproxy->id);
7645 }
7646 }
7647 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007648
7649 /* create the task associated with the proxy */
7650 curproxy->task = task_new();
7651 if (curproxy->task) {
7652 curproxy->task->context = curproxy;
7653 curproxy->task->process = manage_proxy;
7654 /* no need to queue, it will be done automatically if some
7655 * listener gets limited.
7656 */
7657 curproxy->task->expire = TICK_ETERNITY;
7658 } else {
7659 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7660 curproxy->id);
7661 cfgerr++;
7662 }
7663
Willy Tarreaubaaee002006-06-26 02:48:02 +02007664 curproxy = curproxy->next;
7665 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007666
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007667 /* Check multi-process mode compatibility */
7668 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007669 if (global.stats_fe && !global.stats_fe->bind_proc) {
7670 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 +01007671 }
7672 }
7673
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007674 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7675 struct auth_users *curuser;
7676 int g;
7677
7678 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7679 unsigned int group_mask = 0;
7680 char *group = NULL;
7681
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007682 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007683 continue;
7684
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007685 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007686
7687 for (g = 0; g < curuserlist->grpcnt; g++)
7688 if (!strcmp(curuserlist->groups[g], group))
7689 break;
7690
7691 if (g == curuserlist->grpcnt) {
7692 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7693 curuserlist->name, group, curuser->user);
7694 err_code |= ERR_ALERT | ERR_FATAL;
7695 goto out;
7696 }
7697
7698 group_mask |= (1 << g);
7699 }
7700
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007701 free(curuser->u.groups);
7702 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007703 }
7704
7705 for (g = 0; g < curuserlist->grpcnt; g++) {
7706 char *user = NULL;
7707
7708 if (!curuserlist->groupusers[g])
7709 continue;
7710
7711 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7712 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7713 if (!strcmp(curuser->user, user))
7714 break;
7715
7716 if (!curuser) {
7717 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7718 curuserlist->name, user, curuserlist->groups[g]);
7719 err_code |= ERR_ALERT | ERR_FATAL;
7720 goto out;
7721 }
7722
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007723 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007724 }
7725
7726 free(curuserlist->groupusers[g]);
7727 }
7728
7729 free(curuserlist->groupusers);
7730
7731#ifdef DEBUG_AUTH
7732 for (g = 0; g < curuserlist->grpcnt; g++) {
7733 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7734
7735 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007736 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007737 fprintf(stderr, " %s", curuser->user);
7738 }
7739
7740 fprintf(stderr, "\n");
7741 }
7742#endif
7743
Willy Tarreaufbb78422011-06-05 15:38:35 +02007744 }
7745
7746 /* automatically compute fullconn if not set. We must not do it in the
7747 * loop above because cross-references are not yet fully resolved.
7748 */
7749 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7750 /* If <fullconn> is not set, let's set it to 10% of the sum of
7751 * the possible incoming frontend's maxconns.
7752 */
7753 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7754 struct proxy *fe;
7755 int total = 0;
7756
7757 /* sum up the number of maxconns of frontends which
7758 * reference this backend at least once or which are
7759 * the same one ('listen').
7760 */
7761 for (fe = proxy; fe; fe = fe->next) {
7762 struct switching_rule *rule;
7763 struct hdr_exp *exp;
7764 int found = 0;
7765
7766 if (!(fe->cap & PR_CAP_FE))
7767 continue;
7768
7769 if (fe == curproxy) /* we're on a "listen" instance */
7770 found = 1;
7771
7772 if (fe->defbe.be == curproxy) /* "default_backend" */
7773 found = 1;
7774
7775 /* check if a "use_backend" rule matches */
7776 if (!found) {
7777 list_for_each_entry(rule, &fe->switching_rules, list) {
7778 if (rule->be.backend == curproxy) {
7779 found = 1;
7780 break;
7781 }
7782 }
7783 }
7784
7785 /* check if a "reqsetbe" rule matches */
7786 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7787 if (exp->action == ACT_SETBE &&
7788 (struct proxy *)exp->replace == curproxy) {
7789 found = 1;
7790 break;
7791 }
7792 }
7793
7794 /* now we've checked all possible ways to reference a backend
7795 * from a frontend.
7796 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007797 if (!found)
7798 continue;
7799 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007800 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007801 /* we have the sum of the maxconns in <total>. We only
7802 * keep 10% of that sum to set the default fullconn, with
7803 * a hard minimum of 1 (to avoid a divide by zero).
7804 */
7805 curproxy->fullconn = (total + 9) / 10;
7806 if (!curproxy->fullconn)
7807 curproxy->fullconn = 1;
7808 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007809 }
7810
Willy Tarreau056f5682010-06-06 15:51:11 +02007811 /* initialize stick-tables on backend capable proxies. This must not
7812 * be done earlier because the data size may be discovered while parsing
7813 * other proxies.
7814 */
Godbach9703e662013-12-11 21:11:41 +08007815 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7816 if (!stktable_init(&curproxy->table)) {
7817 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7818 cfgerr++;
7819 }
7820 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007821
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007822 /*
7823 * Recount currently required checks.
7824 */
7825
7826 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7827 int optnum;
7828
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007829 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7830 if (curproxy->options & cfg_opts[optnum].val)
7831 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007832
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007833 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7834 if (curproxy->options2 & cfg_opts2[optnum].val)
7835 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007836 }
7837
Willy Tarreau122541c2011-09-07 21:24:49 +02007838 if (peers) {
7839 struct peers *curpeers = peers, **last;
7840 struct peer *p, *pb;
7841
7842 /* Remove all peers sections which don't have a valid listener.
7843 * This can happen when a peers section is never referenced and
7844 * does not contain a local peer.
7845 */
7846 last = &peers;
7847 while (*last) {
7848 curpeers = *last;
7849 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007850 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007851 last = &curpeers->next;
7852 continue;
7853 }
7854
7855 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7856 curpeers->id, localpeer);
7857
7858 p = curpeers->remote;
7859 while (p) {
7860 pb = p->next;
7861 free(p->id);
7862 free(p);
7863 p = pb;
7864 }
7865
7866 /* Destroy and unlink this curpeers section.
7867 * Note: curpeers is backed up into *last.
7868 */
7869 free(curpeers->id);
7870 curpeers = curpeers->next;
7871 free(*last);
7872 *last = curpeers;
7873 }
7874 }
7875
Willy Tarreau34eb6712011-10-24 18:15:04 +02007876 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007877 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007878 MEM_F_SHARED);
7879
Willy Tarreaubb925012009-07-23 13:36:36 +02007880 if (cfgerr > 0)
7881 err_code |= ERR_ALERT | ERR_FATAL;
7882 out:
7883 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007884}
7885
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007886/*
7887 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7888 * parsing sessions.
7889 */
7890void cfg_register_keywords(struct cfg_kw_list *kwl)
7891{
7892 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7893}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007894
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007895/*
7896 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7897 */
7898void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7899{
7900 LIST_DEL(&kwl->list);
7901 LIST_INIT(&kwl->list);
7902}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007903
7904/*
7905 * Local variables:
7906 * c-indent-level: 8
7907 * c-basic-offset: 8
7908 * End:
7909 */