blob: 9993c61d161aeb12d98ae96fb1b5adf3bcdccac3 [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 Tarreaue803de22010-01-21 17:43:04 +0100621 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
622 if (global.tune.client_rcvbuf != 0) {
623 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT;
625 goto out;
626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631 }
632 global.tune.client_rcvbuf = atol(args[1]);
633 }
634 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
635 if (global.tune.server_rcvbuf != 0) {
636 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT;
638 goto out;
639 }
640 if (*(args[1]) == 0) {
641 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
642 err_code |= ERR_ALERT | ERR_FATAL;
643 goto out;
644 }
645 global.tune.server_rcvbuf = atol(args[1]);
646 }
647 else if (!strcmp(args[0], "tune.sndbuf.client")) {
648 if (global.tune.client_sndbuf != 0) {
649 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT;
651 goto out;
652 }
653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.client_sndbuf = atol(args[1]);
659 }
660 else if (!strcmp(args[0], "tune.sndbuf.server")) {
661 if (global.tune.server_sndbuf != 0) {
662 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT;
664 goto out;
665 }
666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
670 }
671 global.tune.server_sndbuf = atol(args[1]);
672 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200673 else if (!strcmp(args[0], "tune.pipesize")) {
674 if (*(args[1]) == 0) {
675 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT | ERR_FATAL;
677 goto out;
678 }
679 global.tune.pipesize = atol(args[1]);
680 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100681 else if (!strcmp(args[0], "tune.http.cookielen")) {
682 if (*(args[1]) == 0) {
683 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
684 err_code |= ERR_ALERT | ERR_FATAL;
685 goto out;
686 }
687 global.tune.cookie_len = atol(args[1]) + 1;
688 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200689 else if (!strcmp(args[0], "tune.http.maxhdr")) {
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.max_http_hdr = atol(args[1]);
696 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100697 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
698#ifdef USE_ZLIB
699 if (*args[1]) {
700 global.tune.zlibmemlevel = atoi(args[1]);
701 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
702 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
703 file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 } else {
708 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
709 file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713#else
714 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717#endif
718 }
719 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
720#ifdef USE_ZLIB
721 if (*args[1]) {
722 global.tune.zlibwindowsize = atoi(args[1]);
723 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
724 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
725 file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729 } else {
730 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
731 file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735#else
736 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739#endif
740 }
William Lallemandf3747832012-11-09 12:33:10 +0100741 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
742 if (*args[1]) {
743 global.tune.comp_maxlevel = atoi(args[1]);
744 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
745 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
746 file, linenum, args[0]);
747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
749 }
750 } else {
751 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
752 file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 else if (!strcmp(args[0], "uid")) {
758 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200759 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 }
768 global.uid = atol(args[1]);
769 }
770 else if (!strcmp(args[0], "gid")) {
771 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200772 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
781 global.gid = atol(args[1]);
782 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200783 /* user/group name handling */
784 else if (!strcmp(args[0], "user")) {
785 struct passwd *ha_user;
786 if (global.uid != 0) {
787 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200788 err_code |= ERR_ALERT;
789 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200790 }
791 errno = 0;
792 ha_user = getpwnam(args[1]);
793 if (ha_user != NULL) {
794 global.uid = (int)ha_user->pw_uid;
795 }
796 else {
797 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 +0200798 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200799 }
800 }
801 else if (!strcmp(args[0], "group")) {
802 struct group *ha_group;
803 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200804 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT;
806 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200807 }
808 errno = 0;
809 ha_group = getgrnam(args[1]);
810 if (ha_group != NULL) {
811 global.gid = (int)ha_group->gr_gid;
812 }
813 else {
814 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 +0200815 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200816 }
817 }
818 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 }
825 global.nbproc = atol(args[1]);
826 }
827 else if (!strcmp(args[0], "maxconn")) {
828 if (global.maxconn != 0) {
829 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 if (*(args[1]) == 0) {
834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 }
838 global.maxconn = atol(args[1]);
839#ifdef SYSTEM_MAXCONN
840 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
841 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);
842 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845#endif /* SYSTEM_MAXCONN */
846 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200847 else if (!strcmp(args[0], "maxsslconn")) {
848#ifdef USE_OPENSSL
849 if (*(args[1]) == 0) {
850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 global.maxsslconn = atol(args[1]);
855#else
Emeric Brun0914df82012-10-02 18:45:42 +0200856 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200859#endif
860 }
Emeric Brun850efd52014-01-29 12:24:34 +0100861 else if (!strcmp(args[0], "ssl-server-verify")) {
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 if (strcmp(args[1],"none") == 0)
868 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
869 else if (strcmp(args[1],"required") == 0)
870 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
871 else {
872 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
875 }
876 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200877 else if (!strcmp(args[0], "maxconnrate")) {
878 if (global.cps_lim != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT;
881 goto out;
882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888 global.cps_lim = atol(args[1]);
889 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200890 else if (!strcmp(args[0], "maxsessrate")) {
891 if (global.sps_lim != 0) {
892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT;
894 goto out;
895 }
896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901 global.sps_lim = atol(args[1]);
902 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200903 else if (!strcmp(args[0], "maxsslrate")) {
904 if (global.ssl_lim != 0) {
905 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT;
907 goto out;
908 }
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
913 }
914 global.ssl_lim = atol(args[1]);
915 }
William Lallemandd85f9172012-11-09 17:05:39 +0100916 else if (!strcmp(args[0], "maxcomprate")) {
917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 global.comp_rate_lim = atoi(args[1]) * 1024;
923 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100924 else if (!strcmp(args[0], "maxpipes")) {
925 if (global.maxpipes != 0) {
926 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT;
928 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100929 }
930 if (*(args[1]) == 0) {
931 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100934 }
935 global.maxpipes = atol(args[1]);
936 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100937 else if (!strcmp(args[0], "maxzlibmem")) {
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 }
William Lallemande3a7d992012-11-20 11:25:20 +0100943 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100944 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100945 else if (!strcmp(args[0], "maxcompcpuusage")) {
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100952 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100953 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957}
958
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 else if (!strcmp(args[0], "ulimit-n")) {
960 if (global.rlimit_nofile != 0) {
961 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT;
963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
965 if (*(args[1]) == 0) {
966 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200967 err_code |= ERR_ALERT | ERR_FATAL;
968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969 }
970 global.rlimit_nofile = atol(args[1]);
971 }
972 else if (!strcmp(args[0], "chroot")) {
973 if (global.chroot != NULL) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT;
976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 }
978 if (*(args[1]) == 0) {
979 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 }
983 global.chroot = strdup(args[1]);
984 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200985 else if (!strcmp(args[0], "description")) {
986 int i, len=0;
987 char *d;
988
989 if (!*args[1]) {
990 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
991 file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995
996 for(i=1; *args[i]; i++)
997 len += strlen(args[i])+1;
998
999 if (global.desc)
1000 free(global.desc);
1001
1002 global.desc = d = (char *)calloc(1, len);
1003
1004 d += sprintf(d, "%s", args[1]);
1005 for(i=2; *args[i]; i++)
1006 d += sprintf(d, " %s", args[i]);
1007 }
1008 else if (!strcmp(args[0], "node")) {
1009 int i;
1010 char c;
1011
1012 for (i=0; args[1][i]; i++) {
1013 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001014 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1015 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001016 break;
1017 }
1018
1019 if (!i || args[1][i]) {
1020 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1021 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026
1027 if (global.node)
1028 free(global.node);
1029
1030 global.node = strdup(args[1]);
1031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 else if (!strcmp(args[0], "pidfile")) {
1033 if (global.pidfile != NULL) {
1034 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 global.pidfile = strdup(args[1]);
1044 }
Emeric Bruned760922010-10-22 17:59:25 +02001045 else if (!strcmp(args[0], "unix-bind")) {
1046 int cur_arg = 1;
1047 while (*(args[cur_arg])) {
1048 if (!strcmp(args[cur_arg], "prefix")) {
1049 if (global.unix_bind.prefix != NULL) {
1050 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1051 err_code |= ERR_ALERT;
1052 cur_arg += 2;
1053 continue;
1054 }
1055
1056 if (*(args[cur_arg+1]) == 0) {
1057 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060 }
1061 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1062 cur_arg += 2;
1063 continue;
1064 }
1065
1066 if (!strcmp(args[cur_arg], "mode")) {
1067
1068 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1069 cur_arg += 2;
1070 continue;
1071 }
1072
1073 if (!strcmp(args[cur_arg], "uid")) {
1074
1075 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1076 cur_arg += 2;
1077 continue;
1078 }
1079
1080 if (!strcmp(args[cur_arg], "gid")) {
1081
1082 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1083 cur_arg += 2;
1084 continue;
1085 }
1086
1087 if (!strcmp(args[cur_arg], "user")) {
1088 struct passwd *user;
1089
1090 user = getpwnam(args[cur_arg + 1]);
1091 if (!user) {
1092 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1093 file, linenum, args[0], args[cur_arg + 1 ]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097
1098 global.unix_bind.ux.uid = user->pw_uid;
1099 cur_arg += 2;
1100 continue;
1101 }
1102
1103 if (!strcmp(args[cur_arg], "group")) {
1104 struct group *group;
1105
1106 group = getgrnam(args[cur_arg + 1]);
1107 if (!group) {
1108 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1109 file, linenum, args[0], args[cur_arg + 1 ]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113
1114 global.unix_bind.ux.gid = group->gr_gid;
1115 cur_arg += 2;
1116 continue;
1117 }
1118
Willy Tarreaub48f9582011-09-05 01:17:06 +02001119 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001120 file, linenum, args[0]);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
1123 }
1124 }
William Lallemand0f99e342011-10-12 17:50:54 +02001125 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1126 /* delete previous herited or defined syslog servers */
1127 struct logsrv *back;
1128 struct logsrv *tmp;
1129
1130 if (*(args[1]) != 0) {
1131 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
1134 }
1135
1136 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1137 LIST_DEL(&tmp->list);
1138 free(tmp);
1139 }
1140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 struct sockaddr_storage *sk;
1143 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001144 struct logsrv *logsrv;
1145
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146 if (*(args[1]) == 0 || *(args[2]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 }
William Lallemand0f99e342011-10-12 17:50:54 +02001151
1152 logsrv = calloc(1, sizeof(struct logsrv));
1153
1154 logsrv->facility = get_log_facility(args[2]);
1155 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001158 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 }
1160
William Lallemand0f99e342011-10-12 17:50:54 +02001161 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001163 logsrv->level = get_log_level(args[3]);
1164 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001167 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 }
1170
William Lallemand0f99e342011-10-12 17:50:54 +02001171 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001172 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001173 logsrv->minlvl = get_log_level(args[4]);
1174 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001175 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001177 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001178 }
1179 }
1180
Willy Tarreau902636f2013-03-10 19:44:48 +01001181 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001182 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001183 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001184 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001185 free(logsrv);
1186 goto out;
1187 }
1188 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001189
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001190 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001191 if (port1 != port2) {
1192 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1193 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001194 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001195 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001196 goto out;
1197 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001198
William Lallemand0f99e342011-10-12 17:50:54 +02001199 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001200 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001201 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203
William Lallemand0f99e342011-10-12 17:50:54 +02001204 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001205 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001206 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1207 char *name;
1208 int len;
1209
1210 if (global.log_send_hostname != NULL) {
1211 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1212 err_code |= ERR_ALERT;
1213 goto out;
1214 }
1215
1216 if (*(args[1]))
1217 name = args[1];
1218 else
1219 name = hostname;
1220
1221 len = strlen(name);
1222
1223 /* We'll add a space after the name to respect the log format */
1224 free(global.log_send_hostname);
1225 global.log_send_hostname = malloc(len + 2);
1226 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1227 }
Kevinm48936af2010-12-22 16:08:21 +00001228 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234 free(global.log_tag);
1235 global.log_tag = strdup(args[1]);
1236 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001237 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1238 if (global.spread_checks != 0) {
1239 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001240 err_code |= ERR_ALERT;
1241 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001242 }
1243 if (*(args[1]) == 0) {
1244 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001247 }
1248 global.spread_checks = atol(args[1]);
1249 if (global.spread_checks < 0 || global.spread_checks > 50) {
1250 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001251 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001254 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1255#ifdef USE_CPU_AFFINITY
1256 int cur_arg, i;
1257 unsigned int proc = 0;
1258 unsigned long cpus = 0;
1259
1260 if (strcmp(args[1], "all") == 0)
1261 proc = 0xFFFFFFFF;
1262 else if (strcmp(args[1], "odd") == 0)
1263 proc = 0x55555555;
1264 else if (strcmp(args[1], "even") == 0)
1265 proc = 0xAAAAAAAA;
1266 else {
1267 proc = atoi(args[1]);
1268 if (proc >= 1 && proc <= 32)
1269 proc = 1 << (proc - 1);
1270 }
1271
1272 if (!proc || !*args[2]) {
1273 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",
1274 file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278
1279 cur_arg = 2;
1280 while (*args[cur_arg]) {
1281 unsigned int low, high;
1282
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001283 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001284 char *dash = strchr(args[cur_arg], '-');
1285
1286 low = high = str2uic(args[cur_arg]);
1287 if (dash)
1288 high = str2uic(dash + 1);
1289
1290 if (high < low) {
1291 unsigned int swap = low;
1292 low = high;
1293 high = swap;
1294 }
1295
1296 if (low < 0 || high >= sizeof(long) * 8) {
1297 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1298 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
1302
1303 while (low <= high)
1304 cpus |= 1UL << low++;
1305 }
1306 else {
1307 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1308 file, linenum, args[0], args[cur_arg]);
1309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
1311 }
1312 cur_arg++;
1313 }
1314 for (i = 0; i < 32; i++)
1315 if (proc & (1 << i))
1316 global.cpu_map[i] = cpus;
1317#else
1318 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321#endif
1322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001324 struct cfg_kw_list *kwl;
1325 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001326 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001327
1328 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1329 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1330 if (kwl->kw[index].section != CFG_GLOBAL)
1331 continue;
1332 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001333 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001334 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001335 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001336 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001337 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001338 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001339 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001340 err_code |= ERR_WARN;
1341 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001342 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001343 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001344 }
1345 }
1346 }
1347
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001349 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001351
Willy Tarreau058e9072009-07-20 09:30:05 +02001352 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001353 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001354 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355}
1356
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001357void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001359 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 defproxy.mode = PR_MODE_TCP;
1361 defproxy.state = PR_STNEW;
1362 defproxy.maxconn = cfg_maxpconn;
1363 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001364
Simon Horman66183002013-02-23 10:16:43 +09001365 defproxy.defsrv.check.inter = DEF_CHKINTR;
1366 defproxy.defsrv.check.fastinter = 0;
1367 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001368 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1369 defproxy.defsrv.agent.fastinter = 0;
1370 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001371 defproxy.defsrv.check.rise = DEF_RISETIME;
1372 defproxy.defsrv.check.fall = DEF_FALLTIME;
1373 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1374 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001375 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001376 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001377 defproxy.defsrv.maxqueue = 0;
1378 defproxy.defsrv.minconn = 0;
1379 defproxy.defsrv.maxconn = 0;
1380 defproxy.defsrv.slowstart = 0;
1381 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1382 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1383 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384}
1385
Willy Tarreauade5ec42010-01-28 19:33:49 +01001386
1387static int create_cond_regex_rule(const char *file, int line,
1388 struct proxy *px, int dir, int action, int flags,
1389 const char *cmd, const char *reg, const char *repl,
1390 const char **cond_start)
1391{
1392 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001393 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001394 const char *err;
1395 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001396 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001397
1398 if (px == &defproxy) {
1399 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto err;
1402 }
1403
1404 if (*reg == 0) {
1405 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto err;
1408 }
1409
1410 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1411 err_code |= ERR_WARN;
1412
Willy Tarreau5321c422010-01-28 20:35:13 +01001413 if (cond_start &&
1414 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001415 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1416 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1417 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001418 err_code |= ERR_ALERT | ERR_FATAL;
1419 goto err;
1420 }
1421 }
1422 else if (cond_start && **cond_start) {
1423 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1424 file, line, cmd, *cond_start);
1425 err_code |= ERR_ALERT | ERR_FATAL;
1426 goto err;
1427 }
1428
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001429 err_code |= warnif_cond_conflicts(cond,
1430 (dir == SMP_OPT_DIR_REQ) ?
1431 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1432 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1433 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001434
Willy Tarreauade5ec42010-01-28 19:33:49 +01001435 preg = calloc(1, sizeof(regex_t));
1436 if (!preg) {
1437 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1438 err_code = ERR_ALERT | ERR_FATAL;
1439 goto err;
1440 }
1441
1442 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1443 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1444 err_code = ERR_ALERT | ERR_FATAL;
1445 goto err;
1446 }
1447
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001448 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001449 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001450 if (repl && err) {
1451 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1452 file, line, cmd, *err);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto err;
1455 }
1456
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001457 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001458 err_code |= ERR_WARN;
1459
Willy Tarreauf4068b62012-05-08 17:37:49 +02001460 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001461 return err_code;
1462 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001463 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001464 free(preg);
1465 return err_code;
1466}
1467
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001470 * Returns the error code, 0 if OK, or any combination of :
1471 * - ERR_ABORT: must abort ASAP
1472 * - ERR_FATAL: we can continue parsing but not start the service
1473 * - ERR_WARN: a warning has been emitted
1474 * - ERR_ALERT: an alert has been emitted
1475 * Only the two first ones can stop processing, the two others are just
1476 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001478int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1479{
1480 static struct peers *curpeers = NULL;
1481 struct peer *newpeer = NULL;
1482 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001483 struct bind_conf *bind_conf;
1484 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001485 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001486 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001487
1488 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001489 if (!*args[1]) {
1490 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1491 err_code |= ERR_ALERT | ERR_FATAL;
1492 goto out;
1493 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001494
1495 err = invalid_char(args[1]);
1496 if (err) {
1497 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1498 file, linenum, *err, args[0], args[1]);
1499 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001500 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001501 }
1502
1503 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1504 /*
1505 * If there are two proxies with the same name only following
1506 * combinations are allowed:
1507 */
1508 if (strcmp(curpeers->id, args[1]) == 0) {
1509 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1510 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1511 err_code |= ERR_WARN;
1512 }
1513 }
1514
1515 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1516 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1517 err_code |= ERR_ALERT | ERR_ABORT;
1518 goto out;
1519 }
1520
1521 curpeers->next = peers;
1522 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001523 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 curpeers->conf.line = linenum;
1525 curpeers->last_change = now.tv_sec;
1526 curpeers->id = strdup(args[1]);
1527 }
1528 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001529 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001530 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001531 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001532
1533 if (!*args[2]) {
1534 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1535 file, linenum, args[0]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539
1540 err = invalid_char(args[1]);
1541 if (err) {
1542 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1543 file, linenum, *err, args[1]);
1544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
1547
1548 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1549 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1550 err_code |= ERR_ALERT | ERR_ABORT;
1551 goto out;
1552 }
1553
1554 /* the peers are linked backwards first */
1555 curpeers->count++;
1556 newpeer->next = curpeers->remote;
1557 curpeers->remote = newpeer;
1558 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001559 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001560 newpeer->conf.line = linenum;
1561
1562 newpeer->last_change = now.tv_sec;
1563 newpeer->id = strdup(args[1]);
1564
Willy Tarreau902636f2013-03-10 19:44:48 +01001565 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001566 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001567 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001568 err_code |= ERR_ALERT | ERR_FATAL;
1569 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001571
1572 proto = protocol_by_family(sk->ss_family);
1573 if (!proto || !proto->connect) {
1574 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1575 file, linenum, args[0], args[1]);
1576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
1578 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001579
1580 if (port1 != port2) {
1581 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1582 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001583 err_code |= ERR_ALERT | ERR_FATAL;
1584 goto out;
1585 }
1586
Willy Tarreau2aa38802013-02-20 19:20:59 +01001587 if (!port1) {
1588 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1589 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001590 err_code |= ERR_ALERT | ERR_FATAL;
1591 goto out;
1592 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001593
Emeric Brun32da3c42010-09-23 18:39:19 +02001594 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001595 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001596 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001597 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001598
Emeric Brun32da3c42010-09-23 18:39:19 +02001599 if (strcmp(newpeer->id, localpeer) == 0) {
1600 /* Current is local peer, it define a frontend */
1601 newpeer->local = 1;
1602
1603 if (!curpeers->peers_fe) {
1604 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1605 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1606 err_code |= ERR_ALERT | ERR_ABORT;
1607 goto out;
1608 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001609
Willy Tarreau237250c2011-07-29 01:49:03 +02001610 init_new_proxy(curpeers->peers_fe);
1611 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001612
1613 curpeers->peers_fe->last_change = now.tv_sec;
1614 curpeers->peers_fe->id = strdup(args[1]);
1615 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001616 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001617 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1618 curpeers->peers_fe->timeout.connect = 5000;
1619 curpeers->peers_fe->accept = peer_accept;
1620 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001621 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1622 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001623
1624 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1625
Willy Tarreau902636f2013-03-10 19:44:48 +01001626 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1627 if (errmsg && *errmsg) {
1628 indent_msg(&errmsg, 2);
1629 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001630 }
1631 else
1632 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1633 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001634 err_code |= ERR_FATAL;
1635 goto out;
1636 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001637
1638 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1639 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1640 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1641 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1642 l->accept = session_accept;
1643 l->handler = process_session;
1644 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1645 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1646 global.maxsock += l->maxconn;
1647 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001648 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001649 else {
1650 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1651 file, linenum, args[0], args[1],
1652 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1653 err_code |= ERR_FATAL;
1654 goto out;
1655 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001656 }
1657 } /* neither "peer" nor "peers" */
1658 else if (*args[0] != 0) {
1659 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662 }
1663
1664out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001665 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001666 return err_code;
1667}
1668
Simon Horman69d29f92013-02-23 15:14:19 +09001669static int init_check(struct check *check, int type, const char * file, int linenum)
1670{
1671 check->type = type;
1672
1673 /* Allocate buffer for requests... */
1674 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1675 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1676 return ERR_ALERT | ERR_ABORT;
1677 }
1678 check->bi->size = global.tune.chksize;
1679
1680 /* Allocate buffer for responses... */
1681 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1682 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1683 return ERR_ALERT | ERR_ABORT;
1684 }
1685 check->bo->size = global.tune.chksize;
1686
1687 /* Allocate buffer for partial results... */
1688 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1689 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1690 return ERR_ALERT | ERR_ABORT;
1691 }
1692
1693 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1694
1695 return 0;
1696}
Emeric Brun32da3c42010-09-23 18:39:19 +02001697
Willy Tarreau3842f002009-06-14 11:39:52 +02001698int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699{
1700 static struct proxy *curproxy = NULL;
1701 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001702 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001703 int rc;
1704 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001705 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001706 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001707 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001708 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001709 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711 if (!strcmp(args[0], "listen"))
1712 rc = PR_CAP_LISTEN;
1713 else if (!strcmp(args[0], "frontend"))
1714 rc = PR_CAP_FE | PR_CAP_RS;
1715 else if (!strcmp(args[0], "backend"))
1716 rc = PR_CAP_BE | PR_CAP_RS;
1717 else if (!strcmp(args[0], "ruleset"))
1718 rc = PR_CAP_RS;
1719 else
1720 rc = PR_CAP_NONE;
1721
1722 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 if (!*args[1]) {
1724 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1725 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_ALERT | ERR_ABORT;
1728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001730
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001731 err = invalid_char(args[1]);
1732 if (err) {
1733 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1734 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001736 }
1737
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001738 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1739 /*
1740 * If there are two proxies with the same name only following
1741 * combinations are allowed:
1742 *
1743 * listen backend frontend ruleset
1744 * listen - - - -
1745 * backend - - OK -
1746 * frontend - OK - -
1747 * ruleset - - - -
1748 */
1749
1750 if (!strcmp(curproxy->id, args[1]) &&
1751 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1752 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001753 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1754 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1755 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001756 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001757 }
1758 }
1759
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1761 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001762 err_code |= ERR_ALERT | ERR_ABORT;
1763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001765
Willy Tarreau97cb7802010-01-03 20:23:58 +01001766 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 curproxy->next = proxy;
1768 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001769 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1770 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001771 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001773 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774
1775 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001776 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001777 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001778
Willy Tarreau4348fad2012-09-20 16:48:07 +02001779 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1780
Willy Tarreau902636f2013-03-10 19:44:48 +01001781 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1782 if (errmsg && *errmsg) {
1783 indent_msg(&errmsg, 2);
1784 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001785 }
1786 else
1787 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1788 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_FATAL;
1790 goto out;
1791 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001792
Willy Tarreau4348fad2012-09-20 16:48:07 +02001793 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001794 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001795 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
1797
1798 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001799 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001800 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001801
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001804 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001805 curproxy->no_options = defproxy.no_options;
1806 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001807 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001808 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001809 curproxy->except_net = defproxy.except_net;
1810 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001811 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001812 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001814 if (defproxy.fwdfor_hdr_len) {
1815 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1816 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1817 }
1818
Willy Tarreaub86db342009-11-30 11:50:16 +01001819 if (defproxy.orgto_hdr_len) {
1820 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1821 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1822 }
1823
Mark Lamourinec2247f02012-01-04 13:02:01 -05001824 if (defproxy.server_id_hdr_len) {
1825 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1826 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1827 }
1828
Willy Tarreau977b8e42006-12-29 14:19:17 +01001829 if (curproxy->cap & PR_CAP_FE) {
1830 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001831 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001832 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833
1834 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001835 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1836 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001837
1838 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840
Willy Tarreau977b8e42006-12-29 14:19:17 +01001841 if (curproxy->cap & PR_CAP_BE) {
1842 curproxy->fullconn = defproxy.fullconn;
1843 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001845 if (defproxy.check_req) {
1846 curproxy->check_req = calloc(1, defproxy.check_len);
1847 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1848 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001851 if (defproxy.expect_str) {
1852 curproxy->expect_str = strdup(defproxy.expect_str);
1853 if (defproxy.expect_regex) {
1854 /* note: this regex is known to be valid */
1855 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1856 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1857 }
1858 }
1859
Willy Tarreau67402132012-05-31 20:40:20 +02001860 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 if (defproxy.cookie_name)
1862 curproxy->cookie_name = strdup(defproxy.cookie_name);
1863 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001864 if (defproxy.cookie_domain)
1865 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001866
Willy Tarreau31936852010-10-06 16:59:56 +02001867 if (defproxy.cookie_maxidle)
1868 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1869
1870 if (defproxy.cookie_maxlife)
1871 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1872
Emeric Brun647caf12009-06-30 17:57:00 +02001873 if (defproxy.rdp_cookie_name)
1874 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1875 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1876
Willy Tarreau01732802007-11-01 22:48:15 +01001877 if (defproxy.url_param_name)
1878 curproxy->url_param_name = strdup(defproxy.url_param_name);
1879 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001880
Benoitaffb4812009-03-25 13:02:10 +01001881 if (defproxy.hh_name)
1882 curproxy->hh_name = strdup(defproxy.hh_name);
1883 curproxy->hh_len = defproxy.hh_len;
1884 curproxy->hh_match_domain = defproxy.hh_match_domain;
1885
Willy Tarreauef9a3602012-12-08 22:29:20 +01001886 if (defproxy.conn_src.iface_name)
1887 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1888 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001889 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001890#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001891 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001892#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001895 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 if (defproxy.capture_name)
1897 curproxy->capture_name = strdup(defproxy.capture_name);
1898 curproxy->capture_namelen = defproxy.capture_namelen;
1899 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001903 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001904 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001905 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001906 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 curproxy->uri_auth = defproxy.uri_auth;
1908 curproxy->mon_net = defproxy.mon_net;
1909 curproxy->mon_mask = defproxy.mon_mask;
1910 if (defproxy.monitor_uri)
1911 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1912 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001913 if (defproxy.defbe.name)
1914 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001915
1916 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001917 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1918 if (curproxy->conf.logformat_string &&
1919 curproxy->conf.logformat_string != default_http_log_format &&
1920 curproxy->conf.logformat_string != default_tcp_log_format &&
1921 curproxy->conf.logformat_string != clf_http_log_format)
1922 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1923
1924 if (defproxy.conf.lfs_file) {
1925 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1926 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1927 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 }
1929
1930 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001931 curproxy->timeout.connect = defproxy.timeout.connect;
1932 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001933 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001934 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001935 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001936 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001937 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001938 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001939 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940 }
1941
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001943
1944 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001945 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001946 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001947 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001948 LIST_INIT(&node->list);
1949 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1950 }
1951
Willy Tarreau62a61232013-04-12 18:13:46 +02001952 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1953 if (curproxy->conf.uniqueid_format_string)
1954 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1955
1956 if (defproxy.conf.uif_file) {
1957 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1958 curproxy->conf.uif_line = defproxy.conf.uif_line;
1959 }
William Lallemanda73203e2012-03-12 12:48:57 +01001960
1961 /* copy default header unique id */
1962 if (defproxy.header_unique_id)
1963 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1964
William Lallemand82fe75c2012-10-23 10:25:10 +02001965 /* default compression options */
1966 if (defproxy.comp != NULL) {
1967 curproxy->comp = calloc(1, sizeof(struct comp));
1968 curproxy->comp->algos = defproxy.comp->algos;
1969 curproxy->comp->types = defproxy.comp->types;
1970 }
1971
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001973 curproxy->conf.used_listener_id = EB_ROOT;
1974 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001975
Willy Tarreau93893792009-07-23 13:19:11 +02001976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 }
1978 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1979 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001980 /* FIXME-20070101: we should do this too at the end of the
1981 * config parsing to free all default values.
1982 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001983 free(defproxy.check_req);
1984 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001985 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001986 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001987 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001988 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001989 free(defproxy.capture_name);
1990 free(defproxy.monitor_uri);
1991 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001992 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001993 free(defproxy.fwdfor_hdr_name);
1994 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001995 free(defproxy.orgto_hdr_name);
1996 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001997 free(defproxy.server_id_hdr_name);
1998 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001999 free(defproxy.expect_str);
2000 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002001
Willy Tarreau62a61232013-04-12 18:13:46 +02002002 if (defproxy.conf.logformat_string != default_http_log_format &&
2003 defproxy.conf.logformat_string != default_tcp_log_format &&
2004 defproxy.conf.logformat_string != clf_http_log_format)
2005 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002006
Willy Tarreau62a61232013-04-12 18:13:46 +02002007 free(defproxy.conf.uniqueid_format_string);
2008 free(defproxy.conf.lfs_file);
2009 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002010
Willy Tarreaua534fea2008-08-03 12:19:50 +02002011 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002012 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002013
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 /* we cannot free uri_auth because it might already be used */
2015 init_default_instance();
2016 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002017 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2018 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002019 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 }
2022 else if (curproxy == NULL) {
2023 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002027
2028 /* update the current file and line being parsed */
2029 curproxy->conf.args.file = curproxy->conf.file;
2030 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002031
2032 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002034 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002035 int cur_arg;
2036
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 if (curproxy == &defproxy) {
2038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044
Willy Tarreau24709282013-03-10 21:32:12 +01002045 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002046 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002051
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002052 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002053
2054 /* use default settings for unix sockets */
2055 bind_conf->ux.uid = global.unix_bind.ux.uid;
2056 bind_conf->ux.gid = global.unix_bind.ux.gid;
2057 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002058
2059 /* NOTE: the following line might create several listeners if there
2060 * are comma-separated IPs or port ranges. So all further processing
2061 * will have to be applied to all listeners created after last_listen.
2062 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002063 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2064 if (errmsg && *errmsg) {
2065 indent_msg(&errmsg, 2);
2066 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002067 }
2068 else
2069 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2070 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002074
Willy Tarreau4348fad2012-09-20 16:48:07 +02002075 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2076 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002077 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002078 }
2079
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002080 cur_arg = 2;
2081 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002082 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002083 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002084 char *err;
2085
Willy Tarreau26982662012-09-12 23:17:10 +02002086 kw = bind_find_kw(args[cur_arg]);
2087 if (kw) {
2088 char *err = NULL;
2089 int code;
2090
2091 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002092 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2093 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002094 cur_arg += 1 + kw->skip ;
2095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
2097 }
2098
Willy Tarreau4348fad2012-09-20 16:48:07 +02002099 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002100 err_code |= code;
2101
2102 if (code) {
2103 if (err && *err) {
2104 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002105 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002106 }
2107 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002108 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2109 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002110 if (code & ERR_FATAL) {
2111 free(err);
2112 cur_arg += 1 + kw->skip;
2113 goto out;
2114 }
2115 }
2116 free(err);
2117 cur_arg += 1 + kw->skip;
2118 continue;
2119 }
2120
Willy Tarreau8638f482012-09-18 18:01:17 +02002121 err = NULL;
2122 if (!bind_dumped) {
2123 bind_dump_kws(&err);
2124 indent_msg(&err, 4);
2125 bind_dumped = 1;
2126 }
2127
2128 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2129 file, linenum, args[0], args[1], args[cur_arg],
2130 err ? " Registered keywords :" : "", err ? err : "");
2131 free(err);
2132
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002135 }
Willy Tarreau93893792009-07-23 13:19:11 +02002136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 }
2138 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2139 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2140 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002145 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002147
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 /* flush useless bits */
2149 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002152 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002155
Willy Tarreau1c47f852006-07-09 08:22:27 +02002156 if (!*args[1]) {
2157 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002161 }
2162
Willy Tarreaua534fea2008-08-03 12:19:50 +02002163 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002164 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002165 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002166 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002167 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2168
Willy Tarreau93893792009-07-23 13:19:11 +02002169 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2172 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2173 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2174 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2175 else {
2176 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002179 }
2180 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002181 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002182 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002183
2184 if (curproxy == &defproxy) {
2185 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002189 }
2190
2191 if (!*args[1]) {
2192 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002196 }
2197
2198 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002199 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002200
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002201 if (curproxy->uuid <= 0) {
2202 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002203 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002206 }
2207
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002208 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2209 if (node) {
2210 struct proxy *target = container_of(node, struct proxy, conf.id);
2211 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2212 file, linenum, proxy_type_str(curproxy), curproxy->id,
2213 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
2216 }
2217 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002218 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002219 else if (!strcmp(args[0], "description")) {
2220 int i, len=0;
2221 char *d;
2222
Cyril Bonté99ed3272010-01-24 23:29:44 +01002223 if (curproxy == &defproxy) {
2224 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2225 file, linenum, args[0]);
2226 err_code |= ERR_ALERT | ERR_FATAL;
2227 goto out;
2228 }
2229
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002230 if (!*args[1]) {
2231 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2232 file, linenum, args[0]);
2233 return -1;
2234 }
2235
2236 for(i=1; *args[i]; i++)
2237 len += strlen(args[i])+1;
2238
2239 d = (char *)calloc(1, len);
2240 curproxy->desc = d;
2241
2242 d += sprintf(d, "%s", args[1]);
2243 for(i=2; *args[i]; i++)
2244 d += sprintf(d, " %s", args[i]);
2245
2246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2248 curproxy->state = PR_STSTOPPED;
2249 }
2250 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2251 curproxy->state = PR_STNEW;
2252 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002253 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2254 int cur_arg = 1;
2255 unsigned int set = 0;
2256
2257 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002258 unsigned int low, high;
2259
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002260 if (strcmp(args[cur_arg], "all") == 0) {
2261 set = 0;
2262 break;
2263 }
2264 else if (strcmp(args[cur_arg], "odd") == 0) {
2265 set |= 0x55555555;
2266 }
2267 else if (strcmp(args[cur_arg], "even") == 0) {
2268 set |= 0xAAAAAAAA;
2269 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002270 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002271 char *dash = strchr(args[cur_arg], '-');
2272
2273 low = high = str2uic(args[cur_arg]);
2274 if (dash)
2275 high = str2uic(dash + 1);
2276
2277 if (high < low) {
2278 unsigned int swap = low;
2279 low = high;
2280 high = swap;
2281 }
2282
2283 if (low < 1 || high > 32) {
2284 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002288 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002289
2290 if (high > global.nbproc) {
2291 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2292 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002294 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002295 while (low <= high)
2296 set |= 1 << (low++ - 1);
2297 }
2298 else {
2299 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2300 file, linenum, args[0]);
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002303 }
2304 cur_arg++;
2305 }
2306 curproxy->bind_proc = set;
2307 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002308 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002309 if (curproxy == &defproxy) {
2310 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002313 }
2314
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002315 err = invalid_char(args[1]);
2316 if (err) {
2317 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2318 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002319 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002320 }
2321
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002322 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002323 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2324 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002327 }
2328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2330 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331
Willy Tarreau977b8e42006-12-29 14:19:17 +01002332 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002334
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 if (*(args[1]) == 0) {
2336 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002341
Willy Tarreau67402132012-05-31 20:40:20 +02002342 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002343 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002344 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002345 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 curproxy->cookie_name = strdup(args[1]);
2347 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002348
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 cur_arg = 2;
2350 while (*(args[cur_arg])) {
2351 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002352 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002355 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
2357 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002358 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 }
2360 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002361 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
2363 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002364 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002366 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002367 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002370 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002372 else if (!strcmp(args[cur_arg], "httponly")) {
2373 curproxy->ck_opts |= PR_CK_HTTPONLY;
2374 }
2375 else if (!strcmp(args[cur_arg], "secure")) {
2376 curproxy->ck_opts |= PR_CK_SECURE;
2377 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002378 else if (!strcmp(args[cur_arg], "domain")) {
2379 if (!*args[cur_arg + 1]) {
2380 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2381 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002384 }
2385
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002386 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002387 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002388 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2389 " dots nor does not start with a dot."
2390 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002391 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002392 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002393 }
2394
2395 err = invalid_domainchar(args[cur_arg + 1]);
2396 if (err) {
2397 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2398 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002401 }
2402
Willy Tarreau68a897b2009-12-03 23:28:34 +01002403 if (!curproxy->cookie_domain) {
2404 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2405 } else {
2406 /* one domain was already specified, add another one by
2407 * building the string which will be returned along with
2408 * the cookie.
2409 */
2410 char *new_ptr;
2411 int new_len = strlen(curproxy->cookie_domain) +
2412 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2413 new_ptr = malloc(new_len);
2414 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2415 free(curproxy->cookie_domain);
2416 curproxy->cookie_domain = new_ptr;
2417 }
Willy Tarreau31936852010-10-06 16:59:56 +02002418 cur_arg++;
2419 }
2420 else if (!strcmp(args[cur_arg], "maxidle")) {
2421 unsigned int maxidle;
2422 const char *res;
2423
2424 if (!*args[cur_arg + 1]) {
2425 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2426 file, linenum, args[cur_arg]);
2427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
2429 }
2430
2431 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2432 if (res) {
2433 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2434 file, linenum, *res, args[cur_arg]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 curproxy->cookie_maxidle = maxidle;
2439 cur_arg++;
2440 }
2441 else if (!strcmp(args[cur_arg], "maxlife")) {
2442 unsigned int maxlife;
2443 const char *res;
2444
2445 if (!*args[cur_arg + 1]) {
2446 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2447 file, linenum, args[cur_arg]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451
2452 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2453 if (res) {
2454 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2455 file, linenum, *res, args[cur_arg]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002460 cur_arg++;
2461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002463 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 +02002464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
2468 cur_arg++;
2469 }
Willy Tarreau67402132012-05-31 20:40:20 +02002470 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2472 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 }
2475
Willy Tarreau67402132012-05-31 20:40:20 +02002476 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2478 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002481
Willy Tarreau67402132012-05-31 20:40:20 +02002482 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002483 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2484 file, linenum);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002488 else if (!strcmp(args[0], "persist")) { /* persist */
2489 if (*(args[1]) == 0) {
2490 Alert("parsing [%s:%d] : missing persist method.\n",
2491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002494 }
2495
2496 if (!strncmp(args[1], "rdp-cookie", 10)) {
2497 curproxy->options2 |= PR_O2_RDPC_PRST;
2498
Emeric Brunb982a3d2010-01-04 15:45:53 +01002499 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002500 const char *beg, *end;
2501
2502 beg = args[1] + 11;
2503 end = strchr(beg, ')');
2504
2505 if (!end || end == beg) {
2506 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2507 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002510 }
2511
2512 free(curproxy->rdp_cookie_name);
2513 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2514 curproxy->rdp_cookie_len = end-beg;
2515 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002516 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002517 free(curproxy->rdp_cookie_name);
2518 curproxy->rdp_cookie_name = strdup("msts");
2519 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2520 }
2521 else { /* syntax */
2522 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002526 }
2527 }
2528 else {
2529 Alert("parsing [%s:%d] : unknown persist method.\n",
2530 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002533 }
2534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002536 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
2542 }
2543
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002546
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002548 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
2553 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002554 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 curproxy->appsession_name = strdup(args[1]);
2556 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2557 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002558 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2559 if (err) {
2560 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2561 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002564 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002565 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002566
Willy Tarreau51041c72007-09-09 21:56:53 +02002567 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_ABORT;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002572
2573 cur_arg = 6;
2574 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002575 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2576 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002577 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002578 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002579 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002580 } else if (!strcmp(args[cur_arg], "prefix")) {
2581 curproxy->options2 |= PR_O2_AS_PFX;
2582 } else if (!strcmp(args[cur_arg], "mode")) {
2583 if (!*args[cur_arg + 1]) {
2584 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2585 file, linenum, args[0], args[cur_arg]);
2586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
2588 }
2589
2590 cur_arg++;
2591 if (!strcmp(args[cur_arg], "query-string")) {
2592 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2593 curproxy->options2 |= PR_O2_AS_M_QS;
2594 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2595 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2596 curproxy->options2 |= PR_O2_AS_M_PP;
2597 } else {
2598 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
2602 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002603 cur_arg++;
2604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 } /* Url App Session */
2606 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002607 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
2615 }
2616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (*(args[4]) == 0) {
2618 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002623 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 curproxy->capture_name = strdup(args[2]);
2625 curproxy->capture_namelen = strlen(curproxy->capture_name);
2626 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 curproxy->to_log |= LW_COOKIE;
2628 }
2629 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2630 struct cap_hdr *hdr;
2631
2632 if (curproxy == &defproxy) {
2633 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 +02002634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 }
2637
2638 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2639 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2640 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
2644
2645 hdr = calloc(sizeof(struct cap_hdr), 1);
2646 hdr->next = curproxy->req_cap;
2647 hdr->name = strdup(args[3]);
2648 hdr->namelen = strlen(args[3]);
2649 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002650 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 hdr->index = curproxy->nb_req_cap++;
2652 curproxy->req_cap = hdr;
2653 curproxy->to_log |= LW_REQHDR;
2654 }
2655 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2656 struct cap_hdr *hdr;
2657
2658 if (curproxy == &defproxy) {
2659 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 +02002660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 }
2663
2664 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2665 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2666 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 }
2670 hdr = calloc(sizeof(struct cap_hdr), 1);
2671 hdr->next = curproxy->rsp_cap;
2672 hdr->name = strdup(args[3]);
2673 hdr->namelen = strlen(args[3]);
2674 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002675 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 hdr->index = curproxy->nb_rsp_cap++;
2677 curproxy->rsp_cap = hdr;
2678 curproxy->to_log |= LW_RSPHDR;
2679 }
2680 else {
2681 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 }
2686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002688 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002690
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 if (*(args[1]) == 0) {
2692 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2693 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 }
2697 curproxy->conn_retries = atol(args[1]);
2698 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002699 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002700 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002701
2702 if (curproxy == &defproxy) {
2703 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707
Willy Tarreau20b0de52012-12-24 15:45:22 +01002708 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2709 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2710 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2711 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002712 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002713 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2714 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 +01002715 file, linenum, args[0]);
2716 err_code |= ERR_WARN;
2717 }
2718
Willy Tarreauff011f22011-01-06 17:51:27 +01002719 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002720
Willy Tarreauff011f22011-01-06 17:51:27 +01002721 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002722 err_code |= ERR_ALERT | ERR_ABORT;
2723 goto out;
2724 }
2725
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002726 err_code |= warnif_cond_conflicts(rule->cond,
2727 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2728 file, linenum);
2729
Willy Tarreauff011f22011-01-06 17:51:27 +01002730 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002731 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002732 else if (!strcmp(args[0], "http-response")) { /* response access control */
2733 struct http_res_rule *rule;
2734
2735 if (curproxy == &defproxy) {
2736 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2742 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2743 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2744 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2745 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2746 file, linenum, args[0]);
2747 err_code |= ERR_WARN;
2748 }
2749
2750 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2751
2752 if (!rule) {
2753 err_code |= ERR_ALERT | ERR_ABORT;
2754 goto out;
2755 }
2756
2757 err_code |= warnif_cond_conflicts(rule->cond,
2758 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2759 file, linenum);
2760
2761 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2762 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002763 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2764 /* set the header name and length into the proxy structure */
2765 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2766 err_code |= ERR_WARN;
2767
2768 if (!*args[1]) {
2769 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2770 file, linenum, args[0]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774
2775 /* set the desired header name */
2776 free(curproxy->server_id_hdr_name);
2777 curproxy->server_id_hdr_name = strdup(args[1]);
2778 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2779 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002780 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002781 if (curproxy == &defproxy) {
2782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002785 }
2786
Willy Tarreauef6494c2010-01-28 17:12:36 +01002787 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002788 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002792 }
2793
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002794 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2795 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2796 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002799 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002800
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002801 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002802 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002803 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002804 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002805 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002806
Cyril Bonté99ed3272010-01-24 23:29:44 +01002807 if (curproxy == &defproxy) {
2808 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
2812
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002813 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002814 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2815 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002818 }
2819
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002820 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002821 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002822 err_code |= warnif_cond_conflicts(rule->cond,
2823 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2824 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002825 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002826 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002827 struct switching_rule *rule;
2828
Willy Tarreaub099aca2008-10-12 17:26:37 +02002829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002833 }
2834
Willy Tarreau55ea7572007-06-17 19:56:27 +02002835 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002836 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002837
2838 if (*(args[1]) == 0) {
2839 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002842 }
2843
Willy Tarreauef6494c2010-01-28 17:12:36 +01002844 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002845 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2846 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002849 }
2850
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002851 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2852 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2853 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002856 }
2857
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002858 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002859
Willy Tarreau55ea7572007-06-17 19:56:27 +02002860 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2861 rule->cond = cond;
2862 rule->be.name = strdup(args[1]);
2863 LIST_INIT(&rule->list);
2864 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2865 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002866 else if (strcmp(args[0], "use-server") == 0) {
2867 struct server_rule *rule;
2868
2869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
2875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2876 err_code |= ERR_WARN;
2877
2878 if (*(args[1]) == 0) {
2879 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883
2884 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2885 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2886 file, linenum, args[0]);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002891 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2892 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2893 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
2897
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002898 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002899
2900 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2901 rule->cond = cond;
2902 rule->srv.name = strdup(args[1]);
2903 LIST_INIT(&rule->list);
2904 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2905 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2906 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002907 else if ((!strcmp(args[0], "force-persist")) ||
2908 (!strcmp(args[0], "ignore-persist"))) {
2909 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002910
2911 if (curproxy == &defproxy) {
2912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916
2917 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2918 err_code |= ERR_WARN;
2919
Willy Tarreauef6494c2010-01-28 17:12:36 +01002920 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002921 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2922 file, linenum, args[0]);
2923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
2925 }
2926
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002927 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2928 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2929 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002934 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2935 * where force-persist is applied.
2936 */
2937 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002938
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002939 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002940 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002941 if (!strcmp(args[0], "force-persist")) {
2942 rule->type = PERSIST_TYPE_FORCE;
2943 } else {
2944 rule->type = PERSIST_TYPE_IGNORE;
2945 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002946 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002947 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002948 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002949 else if (!strcmp(args[0], "stick-table")) {
2950 int myidx = 1;
2951
Emeric Brun32da3c42010-09-23 18:39:19 +02002952 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 curproxy->table.type = (unsigned int)-1;
2954 while (*args[myidx]) {
2955 const char *err;
2956
2957 if (strcmp(args[myidx], "size") == 0) {
2958 myidx++;
2959 if (!*(args[myidx])) {
2960 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2961 file, linenum, args[myidx-1]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2966 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2967 file, linenum, *err, args[myidx-1]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002971 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002973 else if (strcmp(args[myidx], "peers") == 0) {
2974 myidx++;
Godbach50523162013-12-11 19:48:57 +08002975 if (!*(args[myidx])) {
2976 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2977 file, linenum, args[myidx-1]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002981 curproxy->table.peers.name = strdup(args[myidx++]);
2982 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002983 else if (strcmp(args[myidx], "expire") == 0) {
2984 myidx++;
2985 if (!*(args[myidx])) {
2986 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2987 file, linenum, args[myidx-1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2992 if (err) {
2993 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2994 file, linenum, *err, args[myidx-1]);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002999 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003000 }
3001 else if (strcmp(args[myidx], "nopurge") == 0) {
3002 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003003 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 }
3005 else if (strcmp(args[myidx], "type") == 0) {
3006 myidx++;
3007 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3008 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3009 file, linenum, args[myidx]);
3010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
3012 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003013 /* myidx already points to next arg */
3014 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003015 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003016 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003017 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003018
3019 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003020 nw = args[myidx];
3021 while (*nw) {
3022 /* the "store" keyword supports a comma-separated list */
3023 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003024 sa = NULL; /* store arg */
3025 while (*nw && *nw != ',') {
3026 if (*nw == '(') {
3027 *nw = 0;
3028 sa = ++nw;
3029 while (*nw != ')') {
3030 if (!*nw) {
3031 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3032 file, linenum, args[0], cw);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
3036 nw++;
3037 }
3038 *nw = '\0';
3039 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003040 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003041 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003042 if (*nw)
3043 *nw++ = '\0';
3044 type = stktable_get_data_type(cw);
3045 if (type < 0) {
3046 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3047 file, linenum, args[0], cw);
3048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
3050 }
Willy Tarreauac782882010-06-20 10:41:54 +02003051
3052 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3053 switch (err) {
3054 case PE_NONE: break;
3055 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003056 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3057 file, linenum, args[0], cw);
3058 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003059 break;
3060
3061 case PE_ARG_MISSING:
3062 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3063 file, linenum, args[0], cw);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066
3067 case PE_ARG_NOT_USED:
3068 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3069 file, linenum, args[0], cw);
3070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
3072
3073 default:
3074 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3075 file, linenum, args[0], cw);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003078 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003079 }
3080 myidx++;
3081 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003082 else {
3083 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3084 file, linenum, args[myidx]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003087 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003088 }
3089
3090 if (!curproxy->table.size) {
3091 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3092 file, linenum);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096
3097 if (curproxy->table.type == (unsigned int)-1) {
3098 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3099 file, linenum);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103 }
3104 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003105 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003106 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003107 int myidx = 0;
3108 const char *name = NULL;
3109 int flags;
3110
3111 if (curproxy == &defproxy) {
3112 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116
3117 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3118 err_code |= ERR_WARN;
3119 goto out;
3120 }
3121
3122 myidx++;
3123 if ((strcmp(args[myidx], "store") == 0) ||
3124 (strcmp(args[myidx], "store-request") == 0)) {
3125 myidx++;
3126 flags = STK_IS_STORE;
3127 }
3128 else if (strcmp(args[myidx], "store-response") == 0) {
3129 myidx++;
3130 flags = STK_IS_STORE | STK_ON_RSP;
3131 }
3132 else if (strcmp(args[myidx], "match") == 0) {
3133 myidx++;
3134 flags = STK_IS_MATCH;
3135 }
3136 else if (strcmp(args[myidx], "on") == 0) {
3137 myidx++;
3138 flags = STK_IS_MATCH | STK_IS_STORE;
3139 }
3140 else {
3141 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
3146 if (*(args[myidx]) == 0) {
3147 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003152 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003153 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003155 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
3158 }
3159
3160 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003161 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3162 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3163 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003164 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003165 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 goto out;
3167 }
3168 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003169 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3170 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3171 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003172 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003173 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003174 goto out;
3175 }
3176 }
3177
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003178 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003179 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003180
Emeric Brunb982a3d2010-01-04 15:45:53 +01003181 if (strcmp(args[myidx], "table") == 0) {
3182 myidx++;
3183 name = args[myidx++];
3184 }
3185
Willy Tarreauef6494c2010-01-28 17:12:36 +01003186 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003187 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3188 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3189 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003190 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003191 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003192 goto out;
3193 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003194 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003195 else if (*(args[myidx])) {
3196 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3197 file, linenum, args[0], args[myidx]);
3198 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003199 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003200 goto out;
3201 }
Emeric Brun97679e72010-09-23 17:56:44 +02003202 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003203 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003204 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003205 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003206
Emeric Brunb982a3d2010-01-04 15:45:53 +01003207 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3208 rule->cond = cond;
3209 rule->expr = expr;
3210 rule->flags = flags;
3211 rule->table.name = name ? strdup(name) : NULL;
3212 LIST_INIT(&rule->list);
3213 if (flags & STK_ON_RSP)
3214 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3215 else
3216 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003221
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3223 curproxy->uri_auth = NULL; /* we must detach from the default config */
3224
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003225 if (!*args[1]) {
3226 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003227 } else if (!strcmp(args[1], "admin")) {
3228 struct stats_admin_rule *rule;
3229
3230 if (curproxy == &defproxy) {
3231 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
3234 }
3235
3236 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3237 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3238 err_code |= ERR_ALERT | ERR_ABORT;
3239 goto out;
3240 }
3241
3242 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3243 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3244 file, linenum, args[0], args[1]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003248 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3249 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3250 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
3253 }
3254
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003255 err_code |= warnif_cond_conflicts(cond,
3256 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3257 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003258
3259 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3260 rule->cond = cond;
3261 LIST_INIT(&rule->list);
3262 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 } else if (!strcmp(args[1], "uri")) {
3264 if (*(args[2]) == 0) {
3265 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3269 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_ABORT;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 }
3273 } else if (!strcmp(args[1], "realm")) {
3274 if (*(args[2]) == 0) {
3275 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_ABORT;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003283 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003284 unsigned interval;
3285
3286 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3287 if (err) {
3288 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3289 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003292 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_ABORT;
3295 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003296 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003297 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003298 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003299
3300 if (curproxy == &defproxy) {
3301 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
3304 }
3305
3306 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3307 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3308 err_code |= ERR_ALERT | ERR_ABORT;
3309 goto out;
3310 }
3311
Willy Tarreauff011f22011-01-06 17:51:27 +01003312 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3313 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003314 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3315 file, linenum, args[0]);
3316 err_code |= ERR_WARN;
3317 }
3318
Willy Tarreauff011f22011-01-06 17:51:27 +01003319 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003320
Willy Tarreauff011f22011-01-06 17:51:27 +01003321 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003322 err_code |= ERR_ALERT | ERR_ABORT;
3323 goto out;
3324 }
3325
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003326 err_code |= warnif_cond_conflicts(rule->cond,
3327 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3328 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003329 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003330
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 } else if (!strcmp(args[1], "auth")) {
3332 if (*(args[2]) == 0) {
3333 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3337 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_ABORT;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
3341 } else if (!strcmp(args[1], "scope")) {
3342 if (*(args[2]) == 0) {
3343 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3347 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_ALERT | ERR_ABORT;
3349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 }
3351 } else if (!strcmp(args[1], "enable")) {
3352 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3353 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_ABORT;
3355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003357 } else if (!strcmp(args[1], "hide-version")) {
3358 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_ABORT;
3361 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003362 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003363 } else if (!strcmp(args[1], "show-legends")) {
3364 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3365 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3366 err_code |= ERR_ALERT | ERR_ABORT;
3367 goto out;
3368 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003369 } else if (!strcmp(args[1], "show-node")) {
3370
3371 if (*args[2]) {
3372 int i;
3373 char c;
3374
3375 for (i=0; args[2][i]; i++) {
3376 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003377 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3378 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003379 break;
3380 }
3381
3382 if (!i || args[2][i]) {
3383 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3384 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3385 file, linenum, args[0], args[1]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389 }
3390
3391 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3392 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3393 err_code |= ERR_ALERT | ERR_ABORT;
3394 goto out;
3395 }
3396 } else if (!strcmp(args[1], "show-desc")) {
3397 char *desc = NULL;
3398
3399 if (*args[2]) {
3400 int i, len=0;
3401 char *d;
3402
3403 for(i=2; *args[i]; i++)
3404 len += strlen(args[i])+1;
3405
3406 desc = d = (char *)calloc(1, len);
3407
3408 d += sprintf(d, "%s", args[2]);
3409 for(i=3; *args[i]; i++)
3410 d += sprintf(d, " %s", args[i]);
3411 }
3412
3413 if (!*args[2] && !global.desc)
3414 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3415 file, linenum, args[1]);
3416 else {
3417 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3418 free(desc);
3419 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3420 err_code |= ERR_ALERT | ERR_ABORT;
3421 goto out;
3422 }
3423 free(desc);
3424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003426stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003427 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 +01003428 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
3432 }
3433 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003434 int optnum;
3435
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003436 if (*(args[1]) == '\0') {
3437 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3438 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003442
3443 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3444 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003445 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3446 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3447 file, linenum, cfg_opts[optnum].name);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
Willy Tarreau93893792009-07-23 13:19:11 +02003451 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3452 err_code |= ERR_WARN;
3453 goto out;
3454 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003455
Willy Tarreau3842f002009-06-14 11:39:52 +02003456 curproxy->no_options &= ~cfg_opts[optnum].val;
3457 curproxy->options &= ~cfg_opts[optnum].val;
3458
3459 switch (kwm) {
3460 case KWM_STD:
3461 curproxy->options |= cfg_opts[optnum].val;
3462 break;
3463 case KWM_NO:
3464 curproxy->no_options |= cfg_opts[optnum].val;
3465 break;
3466 case KWM_DEF: /* already cleared */
3467 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003468 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003469
Willy Tarreau93893792009-07-23 13:19:11 +02003470 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003471 }
3472 }
3473
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003474 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3475 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003476 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3477 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3478 file, linenum, cfg_opts2[optnum].name);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
Willy Tarreau93893792009-07-23 13:19:11 +02003482 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3483 err_code |= ERR_WARN;
3484 goto out;
3485 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003486
Willy Tarreau3842f002009-06-14 11:39:52 +02003487 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3488 curproxy->options2 &= ~cfg_opts2[optnum].val;
3489
3490 switch (kwm) {
3491 case KWM_STD:
3492 curproxy->options2 |= cfg_opts2[optnum].val;
3493 break;
3494 case KWM_NO:
3495 curproxy->no_options2 |= cfg_opts2[optnum].val;
3496 break;
3497 case KWM_DEF: /* already cleared */
3498 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003499 }
Willy Tarreau93893792009-07-23 13:19:11 +02003500 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003501 }
3502 }
3503
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003504 /* HTTP options override each other. They can be cancelled using
3505 * "no option xxx" which only switches to default mode if the mode
3506 * was this one (useful for cancelling options set in defaults
3507 * sections).
3508 */
3509 if (strcmp(args[1], "httpclose") == 0) {
3510 if (kwm == KWM_STD) {
3511 curproxy->options &= ~PR_O_HTTP_MODE;
3512 curproxy->options |= PR_O_HTTP_PCL;
3513 goto out;
3514 }
3515 else if (kwm == KWM_NO) {
3516 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3517 curproxy->options &= ~PR_O_HTTP_MODE;
3518 goto out;
3519 }
3520 }
3521 else if (strcmp(args[1], "forceclose") == 0) {
3522 if (kwm == KWM_STD) {
3523 curproxy->options &= ~PR_O_HTTP_MODE;
3524 curproxy->options |= PR_O_HTTP_FCL;
3525 goto out;
3526 }
3527 else if (kwm == KWM_NO) {
3528 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3529 curproxy->options &= ~PR_O_HTTP_MODE;
3530 goto out;
3531 }
3532 }
3533 else if (strcmp(args[1], "http-server-close") == 0) {
3534 if (kwm == KWM_STD) {
3535 curproxy->options &= ~PR_O_HTTP_MODE;
3536 curproxy->options |= PR_O_HTTP_SCL;
3537 goto out;
3538 }
3539 else if (kwm == KWM_NO) {
3540 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3541 curproxy->options &= ~PR_O_HTTP_MODE;
3542 goto out;
3543 }
3544 }
3545 else if (strcmp(args[1], "http-keep-alive") == 0) {
3546 if (kwm == KWM_STD) {
3547 curproxy->options &= ~PR_O_HTTP_MODE;
3548 curproxy->options |= PR_O_HTTP_KAL;
3549 goto out;
3550 }
3551 else if (kwm == KWM_NO) {
3552 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3553 curproxy->options &= ~PR_O_HTTP_MODE;
3554 goto out;
3555 }
3556 }
3557 else if (strcmp(args[1], "http-tunnel") == 0) {
3558 if (kwm == KWM_STD) {
3559 curproxy->options &= ~PR_O_HTTP_MODE;
3560 curproxy->options |= PR_O_HTTP_TUN;
3561 goto out;
3562 }
3563 else if (kwm == KWM_NO) {
3564 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3565 curproxy->options &= ~PR_O_HTTP_MODE;
3566 goto out;
3567 }
3568 }
3569
Willy Tarreau3842f002009-06-14 11:39:52 +02003570 if (kwm != KWM_STD) {
3571 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003572 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003575 }
3576
Emeric Brun3a058f32009-06-30 18:26:00 +02003577 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003578 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003580 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003581 if (*(args[2]) != '\0') {
3582 if (!strcmp(args[2], "clf")) {
3583 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003584 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003585 } else {
3586 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003589 }
3590 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003591 if (curproxy->conf.logformat_string != default_http_log_format &&
3592 curproxy->conf.logformat_string != default_tcp_log_format &&
3593 curproxy->conf.logformat_string != clf_http_log_format)
3594 free(curproxy->conf.logformat_string);
3595 curproxy->conf.logformat_string = logformat;
3596
3597 free(curproxy->conf.lfs_file);
3598 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3599 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003600 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003601 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003603 if (curproxy->conf.logformat_string != default_http_log_format &&
3604 curproxy->conf.logformat_string != default_tcp_log_format &&
3605 curproxy->conf.logformat_string != clf_http_log_format)
3606 free(curproxy->conf.logformat_string);
3607 curproxy->conf.logformat_string = default_tcp_log_format;
3608
3609 free(curproxy->conf.lfs_file);
3610 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3611 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 else if (!strcmp(args[1], "tcpka")) {
3614 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003615 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003617
3618 if (curproxy->cap & PR_CAP_FE)
3619 curproxy->options |= PR_O_TCP_CLI_KA;
3620 if (curproxy->cap & PR_CAP_BE)
3621 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
3623 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_WARN;
3626
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003628 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003629 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003630 curproxy->options2 &= ~PR_O2_CHK_ANY;
3631 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 if (!*args[2]) { /* no argument */
3633 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3634 curproxy->check_len = strlen(DEF_CHECK_REQ);
3635 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003636 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 curproxy->check_req = (char *)malloc(reqlen);
3638 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003639 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003641 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 if (*args[4])
3643 reqlen += strlen(args[4]);
3644 else
3645 reqlen += strlen("HTTP/1.0");
3646
3647 curproxy->check_req = (char *)malloc(reqlen);
3648 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003649 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003651 }
3652 else if (!strcmp(args[1], "ssl-hello-chk")) {
3653 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003656
Willy Tarreaua534fea2008-08-03 12:19:50 +02003657 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003658 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003659 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003660 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 }
Willy Tarreau23677902007-05-08 23:50:35 +02003662 else if (!strcmp(args[1], "smtpchk")) {
3663 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003664 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003665 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003666 curproxy->options2 &= ~PR_O2_CHK_ANY;
3667 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003668
3669 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3670 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3671 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3672 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3673 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3674 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3675 curproxy->check_req = (char *)malloc(reqlen);
3676 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3677 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3678 } else {
3679 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3680 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3681 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3682 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3683 }
3684 }
3685 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003686 else if (!strcmp(args[1], "pgsql-check")) {
3687 /* use PostgreSQL request to check servers' health */
3688 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3689 err_code |= ERR_WARN;
3690
3691 free(curproxy->check_req);
3692 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003693 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003694 curproxy->options2 |= PR_O2_PGSQL_CHK;
3695
3696 if (*(args[2])) {
3697 int cur_arg = 2;
3698
3699 while (*(args[cur_arg])) {
3700 if (strcmp(args[cur_arg], "user") == 0) {
3701 char * packet;
3702 uint32_t packet_len;
3703 uint32_t pv;
3704
3705 /* suboption header - needs additional argument for it */
3706 if (*(args[cur_arg+1]) == 0) {
3707 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3708 file, linenum, args[0], args[1], args[cur_arg]);
3709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
3711 }
3712
3713 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3714 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3715 pv = htonl(0x30000); /* protocol version 3.0 */
3716
3717 packet = (char*) calloc(1, packet_len);
3718
3719 memcpy(packet + 4, &pv, 4);
3720
3721 /* copy "user" */
3722 memcpy(packet + 8, "user", 4);
3723
3724 /* copy username */
3725 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3726
3727 free(curproxy->check_req);
3728 curproxy->check_req = packet;
3729 curproxy->check_len = packet_len;
3730
3731 packet_len = htonl(packet_len);
3732 memcpy(packet, &packet_len, 4);
3733 cur_arg += 2;
3734 } else {
3735 /* unknown suboption - catchall */
3736 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3737 file, linenum, args[0], args[1]);
3738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
3740 }
3741 } /* end while loop */
3742 }
3743 }
3744
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003745 else if (!strcmp(args[1], "redis-check")) {
3746 /* use REDIS PING request to check servers' health */
3747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3748 err_code |= ERR_WARN;
3749
3750 free(curproxy->check_req);
3751 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003752 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003753 curproxy->options2 |= PR_O2_REDIS_CHK;
3754
3755 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3756 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3757 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3758 }
3759
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003760 else if (!strcmp(args[1], "mysql-check")) {
3761 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3763 err_code |= ERR_WARN;
3764
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003765 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003766 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003767 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003768 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003769
3770 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3771 * const char mysql40_client_auth_pkt[] = {
3772 * "\x0e\x00\x00" // packet length
3773 * "\x01" // packet number
3774 * "\x00\x00" // client capabilities
3775 * "\x00\x00\x01" // max packet
3776 * "haproxy\x00" // username (null terminated string)
3777 * "\x00" // filler (always 0x00)
3778 * "\x01\x00\x00" // packet length
3779 * "\x00" // packet number
3780 * "\x01" // COM_QUIT command
3781 * };
3782 */
3783
3784 if (*(args[2])) {
3785 int cur_arg = 2;
3786
3787 while (*(args[cur_arg])) {
3788 if (strcmp(args[cur_arg], "user") == 0) {
3789 char *mysqluser;
3790 int packetlen, reqlen, userlen;
3791
3792 /* suboption header - needs additional argument for it */
3793 if (*(args[cur_arg+1]) == 0) {
3794 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3795 file, linenum, args[0], args[1], args[cur_arg]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799 mysqluser = args[cur_arg + 1];
3800 userlen = strlen(mysqluser);
3801 packetlen = userlen + 7;
3802 reqlen = packetlen + 9;
3803
3804 free(curproxy->check_req);
3805 curproxy->check_req = (char *)calloc(1, reqlen);
3806 curproxy->check_len = reqlen;
3807
3808 snprintf(curproxy->check_req, 4, "%c%c%c",
3809 ((unsigned char) packetlen & 0xff),
3810 ((unsigned char) (packetlen >> 8) & 0xff),
3811 ((unsigned char) (packetlen >> 16) & 0xff));
3812
3813 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003814 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003815 curproxy->check_req[8] = 1;
3816 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3817 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3818 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3819 cur_arg += 2;
3820 } else {
3821 /* unknown suboption - catchall */
3822 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3823 file, linenum, args[0], args[1]);
3824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
3826 }
3827 } /* end while loop */
3828 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003829 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003830 else if (!strcmp(args[1], "ldap-check")) {
3831 /* use LDAP request to check servers' health */
3832 free(curproxy->check_req);
3833 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003834 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003835 curproxy->options2 |= PR_O2_LDAP_CHK;
3836
3837 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3838 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3839 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3840 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003841 else if (!strcmp(args[1], "tcp-check")) {
3842 /* use raw TCPCHK send/expect to check servers' health */
3843 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3844 err_code |= ERR_WARN;
3845
3846 free(curproxy->check_req);
3847 curproxy->check_req = NULL;
3848 curproxy->options2 &= ~PR_O2_CHK_ANY;
3849 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3850 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003851 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003852 int cur_arg;
3853
3854 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3855 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003856 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003857
Willy Tarreau87cf5142011-08-19 22:57:24 +02003858 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003859
3860 free(curproxy->fwdfor_hdr_name);
3861 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3862 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3863
3864 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3865 cur_arg = 2;
3866 while (*(args[cur_arg])) {
3867 if (!strcmp(args[cur_arg], "except")) {
3868 /* suboption except - needs additional argument for it */
3869 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3870 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3871 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003874 }
3875 /* flush useless bits */
3876 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003877 cur_arg += 2;
3878 } else if (!strcmp(args[cur_arg], "header")) {
3879 /* suboption header - needs additional argument for it */
3880 if (*(args[cur_arg+1]) == 0) {
3881 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3882 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003885 }
3886 free(curproxy->fwdfor_hdr_name);
3887 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3888 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3889 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003890 } else if (!strcmp(args[cur_arg], "if-none")) {
3891 curproxy->options &= ~PR_O_FF_ALWAYS;
3892 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003893 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003894 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003895 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003896 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003899 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003900 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003901 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003902 else if (!strcmp(args[1], "originalto")) {
3903 int cur_arg;
3904
3905 /* insert x-original-to field, but not for the IP address listed as an except.
3906 * set default options (ie: bitfield, header name, etc)
3907 */
3908
3909 curproxy->options |= PR_O_ORGTO;
3910
3911 free(curproxy->orgto_hdr_name);
3912 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3913 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3914
Willy Tarreau87cf5142011-08-19 22:57:24 +02003915 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003916 cur_arg = 2;
3917 while (*(args[cur_arg])) {
3918 if (!strcmp(args[cur_arg], "except")) {
3919 /* suboption except - needs additional argument for it */
3920 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3921 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3922 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003925 }
3926 /* flush useless bits */
3927 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3928 cur_arg += 2;
3929 } else if (!strcmp(args[cur_arg], "header")) {
3930 /* suboption header - needs additional argument for it */
3931 if (*(args[cur_arg+1]) == 0) {
3932 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3933 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003936 }
3937 free(curproxy->orgto_hdr_name);
3938 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3939 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3940 cur_arg += 2;
3941 } else {
3942 /* unknown suboption - catchall */
3943 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3944 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003947 }
3948 } /* end while loop */
3949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 else {
3951 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 }
Willy Tarreau93893792009-07-23 13:19:11 +02003955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003957 else if (!strcmp(args[0], "default_backend")) {
3958 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003960
3961 if (*(args[1]) == 0) {
3962 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003965 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003966 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003967 curproxy->defbe.name = strdup(args[1]);
3968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003972
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003973 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3974 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 /* enable reconnections to dispatch */
3977 curproxy->options |= PR_O_REDISP;
3978 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003979 else if (!strcmp(args[0], "http-check")) {
3980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003982
3983 if (strcmp(args[1], "disable-on-404") == 0) {
3984 /* enable a graceful server shutdown on an HTTP 404 response */
3985 curproxy->options |= PR_O_DISABLE404;
3986 }
Willy Tarreauef781042010-01-27 11:53:01 +01003987 else if (strcmp(args[1], "send-state") == 0) {
3988 /* enable emission of the apparent state of a server in HTTP checks */
3989 curproxy->options2 |= PR_O2_CHK_SNDST;
3990 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003991 else if (strcmp(args[1], "expect") == 0) {
3992 const char *ptr_arg;
3993 int cur_arg;
3994
3995 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3996 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
4000
4001 cur_arg = 2;
4002 /* consider exclamation marks, sole or at the beginning of a word */
4003 while (*(ptr_arg = args[cur_arg])) {
4004 while (*ptr_arg == '!') {
4005 curproxy->options2 ^= PR_O2_EXP_INV;
4006 ptr_arg++;
4007 }
4008 if (*ptr_arg)
4009 break;
4010 cur_arg++;
4011 }
4012 /* now ptr_arg points to the beginning of a word past any possible
4013 * exclamation mark, and cur_arg is the argument which holds this word.
4014 */
4015 if (strcmp(ptr_arg, "status") == 0) {
4016 if (!*(args[cur_arg + 1])) {
4017 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4018 file, linenum, args[0], args[1], ptr_arg);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004023 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004024 curproxy->expect_str = strdup(args[cur_arg + 1]);
4025 }
4026 else if (strcmp(ptr_arg, "string") == 0) {
4027 if (!*(args[cur_arg + 1])) {
4028 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4029 file, linenum, args[0], args[1], ptr_arg);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
4033 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004034 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004035 curproxy->expect_str = strdup(args[cur_arg + 1]);
4036 }
4037 else if (strcmp(ptr_arg, "rstatus") == 0) {
4038 if (!*(args[cur_arg + 1])) {
4039 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4040 file, linenum, args[0], args[1], ptr_arg);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004045 free(curproxy->expect_str);
4046 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4047 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004048 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4049 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4050 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4051 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055 }
4056 else if (strcmp(ptr_arg, "rstring") == 0) {
4057 if (!*(args[cur_arg + 1])) {
4058 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4059 file, linenum, args[0], args[1], ptr_arg);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004064 free(curproxy->expect_str);
4065 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4066 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004067 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4068 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4069 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4070 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074 }
4075 else {
4076 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4077 file, linenum, args[0], args[1], ptr_arg);
4078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
4080 }
4081 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004082 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004083 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 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004086 }
4087 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004088 else if (!strcmp(args[0], "tcp-check")) {
4089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4090 err_code |= ERR_WARN;
4091
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004092 if (strcmp(args[1], "connect") == 0) {
4093 const char *ptr_arg;
4094 int cur_arg;
4095 struct tcpcheck_rule *tcpcheck;
4096 struct list *l;
4097
4098 /* check if first rule is also a 'connect' action */
4099 l = (struct list *)&curproxy->tcpcheck_rules;
4100 if (l->p != l->n) {
4101 tcpcheck = (struct tcpcheck_rule *)l->n;
4102 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4103 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4104 file, linenum);
4105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
4107 }
4108 }
4109
4110 cur_arg = 2;
4111 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4112 tcpcheck->action = TCPCHK_ACT_CONNECT;
4113
4114 /* parsing each parameters to fill up the rule */
4115 while (*(ptr_arg = args[cur_arg])) {
4116 /* tcp port */
4117 if (strcmp(args[cur_arg], "port") == 0) {
4118 if ( (atol(args[cur_arg + 1]) > 65535) ||
4119 (atol(args[cur_arg + 1]) < 1) ){
4120 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4121 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
4124 }
4125 tcpcheck->port = atol(args[cur_arg + 1]);
4126 cur_arg += 2;
4127 }
4128 /* send proxy protocol */
4129 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4130 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4131 cur_arg++;
4132 }
4133#ifdef USE_OPENSSL
4134 else if (strcmp(args[cur_arg], "ssl") == 0) {
4135 curproxy->options |= PR_O_TCPCHK_SSL;
4136 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4137 cur_arg++;
4138 }
4139#endif /* USE_OPENSSL */
4140 else {
4141#ifdef USE_OPENSSL
4142 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4143#else /* USE_OPENSSL */
4144 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4145#endif /* USE_OPENSSL */
4146 file, linenum, args[0], args[1], args[cur_arg]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150
4151 }
4152
4153 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4154 }
4155 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004156 if (! *(args[2]) ) {
4157 /* SEND string expected */
4158 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4159 file, linenum, args[0], args[1], args[2]);
4160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
4162 } else {
4163 struct tcpcheck_rule *tcpcheck;
4164
4165 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4166
4167 tcpcheck->action = TCPCHK_ACT_SEND;
4168 tcpcheck->string_len = strlen(args[2]);
4169 tcpcheck->string = strdup(args[2]);
4170 tcpcheck->expect_regex = NULL;
4171
4172 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4173 }
4174 }
4175 else if (strcmp(args[1], "send-binary") == 0) {
4176 if (! *(args[2]) ) {
4177 /* SEND binary string expected */
4178 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4179 file, linenum, args[0], args[1], args[2]);
4180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
4182 } else {
4183 struct tcpcheck_rule *tcpcheck;
4184 char *err = NULL;
4185
4186 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4187
4188 tcpcheck->action = TCPCHK_ACT_SEND;
4189 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4190 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4191 file, linenum, args[0], args[1], args[2], err);
4192 err_code |= ERR_ALERT | ERR_FATAL;
4193 goto out;
4194 }
4195 tcpcheck->expect_regex = NULL;
4196
4197 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4198 }
4199 }
4200 else if (strcmp(args[1], "expect") == 0) {
4201 const char *ptr_arg;
4202 int cur_arg;
4203 int inverse = 0;
4204
4205 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4206 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
4209 }
4210
4211 cur_arg = 2;
4212 /* consider exclamation marks, sole or at the beginning of a word */
4213 while (*(ptr_arg = args[cur_arg])) {
4214 while (*ptr_arg == '!') {
4215 inverse = !inverse;
4216 ptr_arg++;
4217 }
4218 if (*ptr_arg)
4219 break;
4220 cur_arg++;
4221 }
4222 /* now ptr_arg points to the beginning of a word past any possible
4223 * exclamation mark, and cur_arg is the argument which holds this word.
4224 */
4225 if (strcmp(ptr_arg, "binary") == 0) {
4226 if (!*(args[cur_arg + 1])) {
4227 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4228 file, linenum, args[0], args[1], ptr_arg);
4229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
4231 }
4232 struct tcpcheck_rule *tcpcheck;
4233 char *err = NULL;
4234
4235 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4236
4237 tcpcheck->action = TCPCHK_ACT_EXPECT;
4238 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4239 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4240 file, linenum, args[0], args[1], args[2], err);
4241 err_code |= ERR_ALERT | ERR_FATAL;
4242 goto out;
4243 }
4244 tcpcheck->expect_regex = NULL;
4245 tcpcheck->inverse = inverse;
4246
4247 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4248 }
4249 else if (strcmp(ptr_arg, "string") == 0) {
4250 if (!*(args[cur_arg + 1])) {
4251 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4252 file, linenum, args[0], args[1], ptr_arg);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 }
4256 struct tcpcheck_rule *tcpcheck;
4257
4258 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4259
4260 tcpcheck->action = TCPCHK_ACT_EXPECT;
4261 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4262 tcpcheck->string = strdup(args[cur_arg + 1]);
4263 tcpcheck->expect_regex = NULL;
4264 tcpcheck->inverse = inverse;
4265
4266 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4267 }
4268 else if (strcmp(ptr_arg, "rstring") == 0) {
4269 if (!*(args[cur_arg + 1])) {
4270 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4271 file, linenum, args[0], args[1], ptr_arg);
4272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
4274 }
4275 struct tcpcheck_rule *tcpcheck;
4276
4277 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4278
4279 tcpcheck->action = TCPCHK_ACT_EXPECT;
4280 tcpcheck->string_len = 0;
4281 tcpcheck->string = NULL;
4282 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4283 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4284 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4285 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4286 err_code |= ERR_ALERT | ERR_FATAL;
4287 goto out;
4288 }
4289 tcpcheck->inverse = inverse;
4290
4291 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4292 }
4293 else {
4294 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4295 file, linenum, args[0], args[1], ptr_arg);
4296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299 }
4300 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004301 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004302 err_code |= ERR_ALERT | ERR_FATAL;
4303 goto out;
4304 }
4305 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004306 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004307 if (curproxy == &defproxy) {
4308 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004311 }
4312
Willy Tarreaub80c2302007-11-30 20:51:32 +01004313 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004314 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004315
4316 if (strcmp(args[1], "fail") == 0) {
4317 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004318 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004319 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4320 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004323 }
4324
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004325 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4326 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4327 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004330 }
4331 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4332 }
4333 else {
4334 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004335 err_code |= ERR_ALERT | ERR_FATAL;
4336 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004337 }
4338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339#ifdef TPROXY
4340 else if (!strcmp(args[0], "transparent")) {
4341 /* enable transparent proxy connections */
4342 curproxy->options |= PR_O_TRANSP;
4343 }
4344#endif
4345 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004346 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004348
Willy Tarreaubaaee002006-06-26 02:48:02 +02004349 if (*(args[1]) == 0) {
4350 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004353 }
4354 curproxy->maxconn = atol(args[1]);
4355 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004356 else if (!strcmp(args[0], "backlog")) { /* backlog */
4357 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004358 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004359
4360 if (*(args[1]) == 0) {
4361 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004364 }
4365 curproxy->backlog = atol(args[1]);
4366 }
Willy Tarreau86034312006-12-29 00:10:33 +01004367 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004368 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004370
Willy Tarreau86034312006-12-29 00:10:33 +01004371 if (*(args[1]) == 0) {
4372 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004375 }
4376 curproxy->fullconn = atol(args[1]);
4377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004378 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4379 if (*(args[1]) == 0) {
4380 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004384 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4385 if (err) {
4386 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4387 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_ALERT | ERR_FATAL;
4389 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004390 }
4391 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 }
4393 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004394 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004395 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004396 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004397
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 if (curproxy == &defproxy) {
4399 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004400 err_code |= ERR_ALERT | ERR_FATAL;
4401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004403 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004404 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004405
Willy Tarreau902636f2013-03-10 19:44:48 +01004406 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004407 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004408 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004409 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004410 goto out;
4411 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004412
4413 proto = protocol_by_family(sk->ss_family);
4414 if (!proto || !proto->connect) {
4415 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4416 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
4419 }
4420
4421 if (port1 != port2) {
4422 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4423 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004426 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004427
4428 if (!port1) {
4429 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4430 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004434
Willy Tarreaud5191e72010-02-09 20:50:45 +01004435 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004436 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004437 }
4438 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004441
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004442 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4443 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004448 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004449 /**
4450 * The syntax for hash-type config element is
4451 * hash-type {map-based|consistent} [[<algo>] avalanche]
4452 *
4453 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4454 */
4455 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004456
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004457 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4458 err_code |= ERR_WARN;
4459
4460 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004461 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4462 }
4463 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004464 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4465 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004466 else if (strcmp(args[1], "avalanche") == 0) {
4467 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]);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004470 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004471 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004472 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
4475 }
Bhaskar98634f02013-10-29 23:30:51 -04004476
4477 /* set the hash function to use */
4478 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004479 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004480 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004481
4482 /* if consistent with no argument, then avalanche modifier is also applied */
4483 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4484 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004485 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004486 /* set the hash function */
4487 if (!strcmp(args[2], "sdbm")) {
4488 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4489 }
4490 else if (!strcmp(args[2], "djb2")) {
4491 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004492 } else if (!strcmp(args[2], "wt6")) {
4493 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004494 }
4495 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004496 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 -05004497 err_code |= ERR_ALERT | ERR_FATAL;
4498 goto out;
4499 }
4500
4501 /* set the hash modifier */
4502 if (!strcmp(args[3], "avalanche")) {
4503 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4504 }
4505 else if (*args[3]) {
4506 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
4509 }
Bhaskar98634f02013-10-29 23:30:51 -04004510 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004511 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004512 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004514 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004515 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004517 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004519 err_code |= ERR_ALERT | ERR_FATAL;
4520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004521 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004522 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004523 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524
4525 if (!*args[2]) {
4526 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4527 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004528 err_code |= ERR_ALERT | ERR_FATAL;
4529 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004531
4532 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004533 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004534 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4535 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004538 }
4539
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004540 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004541 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004542 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004543 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004544
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004545 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4546 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4547 err_code |= ERR_ALERT | ERR_ABORT;
4548 goto out;
4549 }
4550
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004551 /* the servers are linked backwards first */
4552 newsrv->next = curproxy->srv;
4553 curproxy->srv = newsrv;
4554 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004555 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004556 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004557
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004558 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004559 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004560 LIST_INIT(&newsrv->pendconns);
4561 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004562 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004563 newsrv->state = SRV_RUNNING; /* early server setup */
4564 newsrv->last_change = now.tv_sec;
4565 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004566
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004567 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004568 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004569 * - IP: => port=+0, relative
4570 * - IP:N => port=N, absolute
4571 * - IP:+N => port=+N, relative
4572 * - IP:-N => port=-N, relative
4573 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004574 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004575 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004576 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004577 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004578 goto out;
4579 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004580
4581 proto = protocol_by_family(sk->ss_family);
4582 if (!proto || !proto->connect) {
4583 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4584 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004588
4589 if (!port1 || !port2) {
4590 /* no port specified, +offset, -offset */
4591 newsrv->state |= SRV_MAPPORTS;
4592 }
4593 else if (port1 != port2) {
4594 /* port range */
4595 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4596 file, linenum, args[0], args[1], args[2]);
4597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599 }
4600 else {
4601 /* used by checks */
4602 realport = port1;
4603 }
4604
Willy Tarreaud5191e72010-02-09 20:50:45 +01004605 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004606 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4607 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004608
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004609 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004610 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4611 file, linenum, newsrv->addr.ss_family, args[2]);
4612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004615
Simon Hormand60d6912013-11-25 10:46:36 +09004616 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004617 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004618 newsrv->check.inter = curproxy->defsrv.check.inter;
4619 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4620 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004621 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4622 newsrv->agent.port = curproxy->defsrv.agent.port;
4623 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4624 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4625 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004626 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4627 newsrv->minconn = curproxy->defsrv.minconn;
4628 newsrv->maxconn = curproxy->defsrv.maxconn;
4629 newsrv->slowstart = curproxy->defsrv.slowstart;
4630 newsrv->onerror = curproxy->defsrv.onerror;
4631 newsrv->consecutive_errors_limit
4632 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004633#ifdef OPENSSL
4634 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4635#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004636 newsrv->uweight = newsrv->iweight
4637 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004638
Simon Horman69d29f92013-02-23 15:14:19 +09004639 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004640 newsrv->check.rise = curproxy->defsrv.check.rise;
4641 newsrv->check.fall = curproxy->defsrv.check.fall;
4642 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004643 newsrv->check.server = newsrv;
4644
Simon Hormand60d6912013-11-25 10:46:36 +09004645 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004646 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4647 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4648 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004649 newsrv->agent.server = newsrv;
4650
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004651 cur_arg = 3;
4652 } else {
4653 newsrv = &curproxy->defsrv;
4654 cur_arg = 1;
4655 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004656
Willy Tarreaubaaee002006-06-26 02:48:02 +02004657 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004658 if (!strcmp(args[cur_arg], "agent-check")) {
4659 global.maxsock++;
4660 do_agent = 1;
4661 cur_arg += 1;
4662 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4663 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4664 if (err) {
4665 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4666 file, linenum, *err, newsrv->id);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
4670 if (val <= 0) {
4671 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4672 file, linenum, val, args[cur_arg], newsrv->id);
4673 err_code |= ERR_ALERT | ERR_FATAL;
4674 goto out;
4675 }
4676 newsrv->agent.inter = val;
4677 cur_arg += 2;
4678 }
4679 else if (!strcmp(args[cur_arg], "agent-port")) {
4680 global.maxsock++;
4681 newsrv->agent.port = atol(args[cur_arg + 1]);
4682 cur_arg += 2;
4683 }
4684 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 newsrv->cookie = strdup(args[cur_arg + 1]);
4686 newsrv->cklen = strlen(args[cur_arg + 1]);
4687 cur_arg += 2;
4688 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004689 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004690 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4691 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4692 cur_arg += 2;
4693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004695 if (!*args[cur_arg + 1]) {
4696 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4697 file, linenum, args[cur_arg]);
4698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
4700 }
4701
Simon Horman58c32972013-11-25 10:46:38 +09004702 newsrv->check.rise = atol(args[cur_arg + 1]);
4703 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004704 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4705 file, linenum, args[cur_arg]);
4706 err_code |= ERR_ALERT | ERR_FATAL;
4707 goto out;
4708 }
4709
Simon Horman125d0992013-02-24 17:23:38 +09004710 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004711 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 cur_arg += 2;
4713 }
4714 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004715 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004716
4717 if (!*args[cur_arg + 1]) {
4718 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4719 file, linenum, args[cur_arg]);
4720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
4722 }
4723
Simon Horman58c32972013-11-25 10:46:38 +09004724 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004725 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4726 file, linenum, args[cur_arg]);
4727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729 }
4730
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 cur_arg += 2;
4732 }
4733 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004734 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4735 if (err) {
4736 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4737 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004740 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004741 if (val <= 0) {
4742 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4743 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004744 err_code |= ERR_ALERT | ERR_FATAL;
4745 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004746 }
Simon Horman66183002013-02-23 10:16:43 +09004747 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 cur_arg += 2;
4749 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004750 else if (!strcmp(args[cur_arg], "fastinter")) {
4751 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4752 if (err) {
4753 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4754 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004757 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004758 if (val <= 0) {
4759 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4760 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004763 }
Simon Horman66183002013-02-23 10:16:43 +09004764 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004765 cur_arg += 2;
4766 }
4767 else if (!strcmp(args[cur_arg], "downinter")) {
4768 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4769 if (err) {
4770 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4771 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004772 err_code |= ERR_ALERT | ERR_FATAL;
4773 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004774 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004775 if (val <= 0) {
4776 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4777 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004780 }
Simon Horman66183002013-02-23 10:16:43 +09004781 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004782 cur_arg += 2;
4783 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004784 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004785 struct sockaddr_storage *sk;
4786 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004787 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004788
Willy Tarreau902636f2013-03-10 19:44:48 +01004789 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004790 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004791 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004792 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004793 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004794 goto out;
4795 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004796
4797 proto = protocol_by_family(sk->ss_family);
4798 if (!proto || !proto->connect) {
4799 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004800 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004804
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004805 if (port1 != port2) {
4806 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4807 file, linenum, args[cur_arg], args[cur_arg + 1]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 }
4811
Simon Horman66183002013-02-23 10:16:43 +09004812 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004813 cur_arg += 2;
4814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004815 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004816 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004817 cur_arg += 2;
4818 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004819 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 newsrv->state |= SRV_BACKUP;
4821 cur_arg ++;
4822 }
Simon Hormanfa461682011-06-25 09:39:49 +09004823 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4824 newsrv->state |= SRV_NON_STICK;
4825 cur_arg ++;
4826 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004827 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4828 newsrv->state |= SRV_SEND_PROXY;
4829 cur_arg ++;
4830 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004831 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4832 newsrv->check.send_proxy = 1;
4833 cur_arg ++;
4834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 else if (!strcmp(args[cur_arg], "weight")) {
4836 int w;
4837 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004838 if (w < 0 || w > SRV_UWGHT_MAX) {
4839 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4840 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004843 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004844 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 cur_arg += 2;
4846 }
4847 else if (!strcmp(args[cur_arg], "minconn")) {
4848 newsrv->minconn = atol(args[cur_arg + 1]);
4849 cur_arg += 2;
4850 }
4851 else if (!strcmp(args[cur_arg], "maxconn")) {
4852 newsrv->maxconn = atol(args[cur_arg + 1]);
4853 cur_arg += 2;
4854 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004855 else if (!strcmp(args[cur_arg], "maxqueue")) {
4856 newsrv->maxqueue = atol(args[cur_arg + 1]);
4857 cur_arg += 2;
4858 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004859 else if (!strcmp(args[cur_arg], "slowstart")) {
4860 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004861 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004862 if (err) {
4863 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4864 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004867 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004868 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004869 cur_arg += 2;
4870 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004871 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004872
4873 if (!*args[cur_arg + 1]) {
4874 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4875 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004878 }
4879
4880 newsrv->trackit = strdup(args[cur_arg + 1]);
4881
4882 cur_arg += 2;
4883 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004884 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 global.maxsock++;
4886 do_check = 1;
4887 cur_arg += 1;
4888 }
Willy Tarreau96839092010-03-29 10:02:24 +02004889 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4890 newsrv->state |= SRV_MAINTAIN;
4891 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004892 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004893 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004894 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004895 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004896 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004897 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004898 if (!strcmp(args[cur_arg + 1], "none"))
4899 newsrv->observe = HANA_OBS_NONE;
4900 else if (!strcmp(args[cur_arg + 1], "layer4"))
4901 newsrv->observe = HANA_OBS_LAYER4;
4902 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4903 if (curproxy->mode != PR_MODE_HTTP) {
4904 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4905 file, linenum, args[cur_arg + 1]);
4906 err_code |= ERR_ALERT;
4907 }
4908 newsrv->observe = HANA_OBS_LAYER7;
4909 }
4910 else {
4911 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004912 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004913 file, linenum, args[cur_arg], args[cur_arg + 1]);
4914 err_code |= ERR_ALERT | ERR_FATAL;
4915 goto out;
4916 }
4917
4918 cur_arg += 2;
4919 }
4920 else if (!strcmp(args[cur_arg], "on-error")) {
4921 if (!strcmp(args[cur_arg + 1], "fastinter"))
4922 newsrv->onerror = HANA_ONERR_FASTINTER;
4923 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4924 newsrv->onerror = HANA_ONERR_FAILCHK;
4925 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4926 newsrv->onerror = HANA_ONERR_SUDDTH;
4927 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4928 newsrv->onerror = HANA_ONERR_MARKDWN;
4929 else {
4930 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004931 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004932 file, linenum, args[cur_arg], args[cur_arg + 1]);
4933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
4935 }
4936
4937 cur_arg += 2;
4938 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004939 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4940 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4941 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4942 else {
4943 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4944 file, linenum, args[cur_arg], args[cur_arg + 1]);
4945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
4947 }
4948
4949 cur_arg += 2;
4950 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004951 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4952 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4953 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4954 else {
4955 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4956 file, linenum, args[cur_arg], args[cur_arg + 1]);
4957 err_code |= ERR_ALERT | ERR_FATAL;
4958 goto out;
4959 }
4960
4961 cur_arg += 2;
4962 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004963 else if (!strcmp(args[cur_arg], "error-limit")) {
4964 if (!*args[cur_arg + 1]) {
4965 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4966 file, linenum, args[cur_arg]);
4967 err_code |= ERR_ALERT | ERR_FATAL;
4968 goto out;
4969 }
4970
4971 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4972
4973 if (newsrv->consecutive_errors_limit <= 0) {
4974 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4975 file, linenum, args[cur_arg]);
4976 err_code |= ERR_ALERT | ERR_FATAL;
4977 goto out;
4978 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004979 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004980 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004981 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004982 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004983 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004984 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004985
Willy Tarreaubaaee002006-06-26 02:48:02 +02004986 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004987 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4988 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004992
Willy Tarreauef9a3602012-12-08 22:29:20 +01004993 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004994 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004995 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004996 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004997 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004998 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004999 goto out;
5000 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005001
5002 proto = protocol_by_family(sk->ss_family);
5003 if (!proto || !proto->connect) {
5004 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5005 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
5008 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005009
Willy Tarreauef9a3602012-12-08 22:29:20 +01005010 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005011
5012 if (port_low != port_high) {
5013 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005014
5015 if (!port_low || !port_high) {
5016 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
5017 file, linenum, args[cur_arg], args[cur_arg + 1]);
5018 err_code |= ERR_ALERT | ERR_FATAL;
5019 goto out;
5020 }
5021
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005022 if (port_low <= 0 || port_low > 65535 ||
5023 port_high <= 0 || port_high > 65535 ||
5024 port_low > port_high) {
5025 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
5026 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02005027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005029 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005030 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
5031 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
5032 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005033 }
5034
Willy Tarreaubaaee002006-06-26 02:48:02 +02005035 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005036 while (*(args[cur_arg])) {
5037 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005038#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5039#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005040 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01005041 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
5042 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005045 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005046#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005047 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005048 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01005049 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005052 }
5053 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005054 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5055 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005056 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005057 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5058 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005059 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5060 char *name, *end;
5061
5062 name = args[cur_arg+1] + 7;
5063 while (isspace(*name))
5064 name++;
5065
5066 end = name;
5067 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5068 end++;
5069
Willy Tarreauef9a3602012-12-08 22:29:20 +01005070 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5071 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5072 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5073 newsrv->conn_src.bind_hdr_len = end - name;
5074 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5075 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5076 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005077
5078 /* now look for an occurrence number */
5079 while (isspace(*end))
5080 end++;
5081 if (*end == ',') {
5082 end++;
5083 name = end;
5084 if (*end == '-')
5085 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005086 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005087 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005088 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005089 }
5090
Willy Tarreauef9a3602012-12-08 22:29:20 +01005091 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005092 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5093 " occurrences values smaller than %d.\n",
5094 file, linenum, MAX_HDR_HISTORY);
5095 err_code |= ERR_ALERT | ERR_FATAL;
5096 goto out;
5097 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005098 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005099 struct sockaddr_storage *sk;
5100 int port1, port2;
5101
Willy Tarreau902636f2013-03-10 19:44:48 +01005102 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005103 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005104 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005105 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005106 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005107 goto out;
5108 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005109
5110 proto = protocol_by_family(sk->ss_family);
5111 if (!proto || !proto->connect) {
5112 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5113 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005117
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005118 if (port1 != port2) {
5119 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5120 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
5123 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005124 newsrv->conn_src.tproxy_addr = *sk;
5125 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005126 }
5127 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005128#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005129 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005130#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005131 cur_arg += 2;
5132 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005133#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005134 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005135 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005136 err_code |= ERR_ALERT | ERR_FATAL;
5137 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005138#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005139 } /* "usesrc" */
5140
5141 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5142#ifdef SO_BINDTODEVICE
5143 if (!*args[cur_arg + 1]) {
5144 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5145 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005146 err_code |= ERR_ALERT | ERR_FATAL;
5147 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005148 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005149 free(newsrv->conn_src.iface_name);
5150 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5151 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005152 global.last_checks |= LSTCHK_NETADM;
5153#else
5154 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5155 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005158#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005159 cur_arg += 2;
5160 continue;
5161 }
5162 /* this keyword in not an option of "source" */
5163 break;
5164 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005166 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005167 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5168 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005173 static int srv_dumped;
5174 struct srv_kw *kw;
5175 char *err;
5176
5177 kw = srv_find_kw(args[cur_arg]);
5178 if (kw) {
5179 char *err = NULL;
5180 int code;
5181
5182 if (!kw->parse) {
5183 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5184 file, linenum, args[0], args[1], args[cur_arg]);
5185 cur_arg += 1 + kw->skip ;
5186 err_code |= ERR_ALERT | ERR_FATAL;
5187 goto out;
5188 }
5189
5190 if (defsrv && !kw->default_ok) {
5191 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5192 file, linenum, args[0], args[1], args[cur_arg]);
5193 cur_arg += 1 + kw->skip ;
5194 err_code |= ERR_ALERT;
5195 continue;
5196 }
5197
5198 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5199 err_code |= code;
5200
5201 if (code) {
5202 if (err && *err) {
5203 indent_msg(&err, 2);
5204 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5205 }
5206 else
5207 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5208 file, linenum, args[0], args[1], args[cur_arg]);
5209 if (code & ERR_FATAL) {
5210 free(err);
5211 cur_arg += 1 + kw->skip;
5212 goto out;
5213 }
5214 }
5215 free(err);
5216 cur_arg += 1 + kw->skip;
5217 continue;
5218 }
5219
5220 err = NULL;
5221 if (!srv_dumped) {
5222 srv_dump_kws(&err);
5223 indent_msg(&err, 4);
5224 srv_dumped = 1;
5225 }
5226
5227 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5228 file, linenum, args[0], args[1], args[cur_arg],
5229 err ? " Registered keywords :" : "", err ? err : "");
5230 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005231
Willy Tarreau93893792009-07-23 13:19:11 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 }
5235 }
5236
Simon Horman8c3d0be2013-11-25 10:46:40 +09005237 /* Set initial drain state using now-configured weight */
5238 set_server_drain_state(newsrv);
5239
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005241 int ret;
5242
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005243 if (newsrv->trackit) {
5244 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5245 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005248 }
5249
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005250 /* If neither a port nor an addr was specified and no check transport
5251 * layer is forced, then the transport layer used by the checks is the
5252 * same as for the production traffic. Otherwise we use raw_sock by
5253 * default, unless one is specified.
5254 */
Simon Horman66183002013-02-23 10:16:43 +09005255 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005256#ifdef USE_OPENSSL
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005257 newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
Willy Tarreau71516332012-10-10 23:01:14 +02005258#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005259 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5260 }
Simon Horman66183002013-02-23 10:16:43 +09005261 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005262 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005263 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005264
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005265 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005266 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005267
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005268 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005269 /* not yet valid, because no port was set on
5270 * the server either. We'll check if we have
5271 * a known port on the first listener.
5272 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005273 struct listener *l;
5274
5275 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005276 newsrv->check.port = get_host_port(&l->addr);
5277 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005278 break;
5279 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005280 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005281 /*
5282 * We need at least a service port, a check port or the first tcp-check rule must
5283 * be a 'connect' one
5284 */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005285 if (!newsrv->check.port) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005286 struct tcpcheck_rule *n = NULL, *r = NULL;
5287 struct list *l;
5288
5289 r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
5290 if (!r) {
5291 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5292 file, linenum, newsrv->id);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
5297 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",
5298 file, linenum, newsrv->id);
5299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
5301 }
5302 else {
5303 /* scan the tcp-check ruleset to ensure a port has been configured */
5304 l = &newsrv->proxy->tcpcheck_rules;
5305 list_for_each_entry(n, l, list) {
5306 r = (struct tcpcheck_rule *)n->list.p;
5307 if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
5308 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",
5309 file, linenum, newsrv->id);
5310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 }
5314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005315 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005316
Willy Tarreau2f075e92013-12-03 11:11:34 +01005317 /* note: check type will be set during the config review phase */
5318 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005319 if (ret) {
5320 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005321 goto out;
5322 }
5323
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005324 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 }
5326
Simon Hormand60d6912013-11-25 10:46:36 +09005327 if (do_agent) {
5328 int ret;
5329
5330 if (!newsrv->agent.port) {
5331 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5332 file, linenum, newsrv->id);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336
5337 if (!newsrv->agent.inter)
5338 newsrv->agent.inter = newsrv->check.inter;
5339
5340 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5341 if (ret) {
5342 err_code |= ret;
5343 goto out;
5344 }
5345
Willy Tarreau33434322013-12-11 21:15:19 +01005346 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005347 }
5348
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005349 if (!defsrv) {
5350 if (newsrv->state & SRV_BACKUP)
5351 curproxy->srv_bck++;
5352 else
5353 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005354
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005355 newsrv->prev_state = newsrv->state;
5356 }
William Lallemanda73203e2012-03-12 12:48:57 +01005357 }
5358
5359 else if (strcmp(args[0], "unique-id-format") == 0) {
5360 if (!*(args[1])) {
5361 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
5364 }
William Lallemand3203ff42012-11-11 17:30:56 +01005365 if (*(args[2])) {
5366 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005370 free(curproxy->conf.uniqueid_format_string);
5371 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005372
Willy Tarreau62a61232013-04-12 18:13:46 +02005373 free(curproxy->conf.uif_file);
5374 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5375 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005376 }
William Lallemanda73203e2012-03-12 12:48:57 +01005377
5378 else if (strcmp(args[0], "unique-id-header") == 0) {
5379 if (!*(args[1])) {
5380 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5381 err_code |= ERR_ALERT | ERR_FATAL;
5382 goto out;
5383 }
5384 free(curproxy->header_unique_id);
5385 curproxy->header_unique_id = strdup(args[1]);
5386 }
5387
William Lallemand723b73a2012-02-08 16:37:49 +01005388 else if (strcmp(args[0], "log-format") == 0) {
5389 if (!*(args[1])) {
5390 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
5393 }
William Lallemand3203ff42012-11-11 17:30:56 +01005394 if (*(args[2])) {
5395 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005399
Willy Tarreau62a61232013-04-12 18:13:46 +02005400 if (curproxy->conf.logformat_string != default_http_log_format &&
5401 curproxy->conf.logformat_string != default_tcp_log_format &&
5402 curproxy->conf.logformat_string != clf_http_log_format)
5403 free(curproxy->conf.logformat_string);
5404 curproxy->conf.logformat_string = strdup(args[1]);
5405
5406 free(curproxy->conf.lfs_file);
5407 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5408 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005409
5410 /* get a chance to improve log-format error reporting by
5411 * reporting the correct line-number when possible.
5412 */
5413 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5414 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5415 file, linenum, curproxy->id);
5416 err_code |= ERR_WARN;
5417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005418 }
William Lallemand723b73a2012-02-08 16:37:49 +01005419
William Lallemand0f99e342011-10-12 17:50:54 +02005420 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5421 /* delete previous herited or defined syslog servers */
5422 struct logsrv *back;
5423
5424 if (*(args[1]) != 0) {
5425 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
5429
William Lallemand723b73a2012-02-08 16:37:49 +01005430 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5431 LIST_DEL(&tmplogsrv->list);
5432 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005433 }
5434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005436 struct logsrv *logsrv;
5437
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005439 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005440 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005441 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005442 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005443 LIST_INIT(&node->list);
5444 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5445 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 }
5447 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005448 struct sockaddr_storage *sk;
5449 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005450
5451 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005452
William Lallemand0f99e342011-10-12 17:50:54 +02005453 logsrv->facility = get_log_facility(args[2]);
5454 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
5458
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459 }
5460
William Lallemand0f99e342011-10-12 17:50:54 +02005461 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005463 logsrv->level = get_log_level(args[3]);
5464 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005465 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
5468
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 }
5470 }
5471
William Lallemand0f99e342011-10-12 17:50:54 +02005472 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005473 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005474 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005475 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005476 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005480 }
5481 }
5482
Willy Tarreau902636f2013-03-10 19:44:48 +01005483 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005484 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005485 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005486 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005487 goto out;
5488 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005489
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005490 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005491
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005492 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005493 if (port1 != port2) {
5494 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5495 file, linenum, args[0], args[1]);
5496 err_code |= ERR_ALERT | ERR_FATAL;
5497 goto out;
5498 }
5499
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005500 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005501 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005502 }
William Lallemand0f99e342011-10-12 17:50:54 +02005503
5504 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005505 }
5506 else {
5507 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5508 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005509 err_code |= ERR_ALERT | ERR_FATAL;
5510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005511 }
5512 }
5513 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005514 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005515 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005516 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005517 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005518
Willy Tarreau977b8e42006-12-29 14:19:17 +01005519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005520 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005521
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005523 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5524 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005525 err_code |= ERR_ALERT | ERR_FATAL;
5526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005528
5529 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005530 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5531 free(curproxy->conn_src.iface_name);
5532 curproxy->conn_src.iface_name = NULL;
5533 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005534
Willy Tarreau902636f2013-03-10 19:44:48 +01005535 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005536 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005537 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005538 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005539 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005540 goto out;
5541 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005542
5543 proto = protocol_by_family(sk->ss_family);
5544 if (!proto || !proto->connect) {
5545 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005546 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
5549 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005550
5551 if (port1 != port2) {
5552 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5553 file, linenum, args[0], args[1]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
5557
Willy Tarreauef9a3602012-12-08 22:29:20 +01005558 curproxy->conn_src.source_addr = *sk;
5559 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005560
5561 cur_arg = 2;
5562 while (*(args[cur_arg])) {
5563 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005564#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5565#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005566 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005567 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5568 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005569 err_code |= ERR_ALERT | ERR_FATAL;
5570 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005571 }
5572#endif
5573 if (!*args[cur_arg + 1]) {
5574 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5575 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005578 }
5579
5580 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005581 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5582 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005583 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005584 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5585 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005586 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5587 char *name, *end;
5588
5589 name = args[cur_arg+1] + 7;
5590 while (isspace(*name))
5591 name++;
5592
5593 end = name;
5594 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5595 end++;
5596
Willy Tarreauef9a3602012-12-08 22:29:20 +01005597 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5598 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5599 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5600 curproxy->conn_src.bind_hdr_len = end - name;
5601 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5602 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5603 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005604
5605 /* now look for an occurrence number */
5606 while (isspace(*end))
5607 end++;
5608 if (*end == ',') {
5609 end++;
5610 name = end;
5611 if (*end == '-')
5612 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005613 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005614 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005615 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005616 }
5617
Willy Tarreauef9a3602012-12-08 22:29:20 +01005618 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005619 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5620 " occurrences values smaller than %d.\n",
5621 file, linenum, MAX_HDR_HISTORY);
5622 err_code |= ERR_ALERT | ERR_FATAL;
5623 goto out;
5624 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005625 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005626 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005627
Willy Tarreau902636f2013-03-10 19:44:48 +01005628 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005629 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005630 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005631 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005632 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005633 goto out;
5634 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005635
5636 proto = protocol_by_family(sk->ss_family);
5637 if (!proto || !proto->connect) {
5638 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5639 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
5642 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005643
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005644 if (port1 != port2) {
5645 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5646 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005650 curproxy->conn_src.tproxy_addr = *sk;
5651 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005652 }
5653 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005654#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005655 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005656#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005657#else /* no TPROXY support */
5658 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005659 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005662#endif
5663 cur_arg += 2;
5664 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005665 }
5666
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005667 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5668#ifdef SO_BINDTODEVICE
5669 if (!*args[cur_arg + 1]) {
5670 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5671 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005672 err_code |= ERR_ALERT | ERR_FATAL;
5673 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005674 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005675 free(curproxy->conn_src.iface_name);
5676 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5677 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005678 global.last_checks |= LSTCHK_NETADM;
5679#else
5680 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5681 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005684#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005685 cur_arg += 2;
5686 continue;
5687 }
5688 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005689 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005694 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5695 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5696 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005697 err_code |= ERR_ALERT | ERR_FATAL;
5698 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005700 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005701 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005702 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5703 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005706 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005707
5708 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005709 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005710 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005711 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005712 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 }
5714 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005715 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005716 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005717 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005718 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
5721 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005722 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005723 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005724 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005725 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
5728 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005729 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005730 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005731 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005732 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 }
5735 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005736 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005737 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005738 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005739 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005742 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005743 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005744 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005745 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005746 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005747 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005748 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005749 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005750 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005751 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005752 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005753 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005754 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005755 }
5756 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005757 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005758 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005759 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005760 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005761 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005762 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005764 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005765 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5766 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005769 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005770
5771 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005772 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005773 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005774 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005776 }
5777 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005778 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005779 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005780 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005781 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005783 }
5784 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005785 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005786 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005787 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005788 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 }
5791 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005792 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005793 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005794 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005795 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005797 }
5798 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005799 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005800 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005801 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005802 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005803 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005804 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005805 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005806 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005807 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005808 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005809 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005810 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005811 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005812 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005813 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005814
Willy Tarreaubaaee002006-06-26 02:48:02 +02005815 if (curproxy == &defproxy) {
5816 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005820 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005821 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823 if (*(args[1]) == 0) {
5824 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005825 err_code |= ERR_ALERT | ERR_FATAL;
5826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005828
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005829 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005830 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5831 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5832 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005833 err_code |= ERR_ALERT | ERR_FATAL;
5834 goto out;
5835 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005836 err_code |= warnif_cond_conflicts(cond,
5837 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5838 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005839 }
5840 else if (*args[2]) {
5841 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5842 file, linenum, args[0], args[2]);
5843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
5845 }
5846
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005847 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005848 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005849 wl->s = strdup(args[1]);
5850 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005851 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005852 }
5853 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005854 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5856 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005860
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_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005863 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005864 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 }
5867 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005868 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005869 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005870 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005871 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 }
5874 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005875 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005876 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005877 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005878 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005879 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 }
5881 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005882 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5884 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 }
5888
Willy Tarreauade5ec42010-01-28 19:33:49 +01005889 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005890 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005891 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005892 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005893 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 }
5895 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005896 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005897 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005898 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005899 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005901 }
5902 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005903 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005904 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005905 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005906 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
5909 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005910 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005911
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 if (curproxy == &defproxy) {
5913 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005917 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005918 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919
Willy Tarreaubaaee002006-06-26 02:48:02 +02005920 if (*(args[1]) == 0) {
5921 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005922 err_code |= ERR_ALERT | ERR_FATAL;
5923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 }
5925
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005926 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005927 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5928 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5929 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005930 err_code |= ERR_ALERT | ERR_FATAL;
5931 goto out;
5932 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005933 err_code |= warnif_cond_conflicts(cond,
5934 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5935 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005936 }
5937 else if (*args[2]) {
5938 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5939 file, linenum, args[0], args[2]);
5940 err_code |= ERR_ALERT | ERR_FATAL;
5941 goto out;
5942 }
5943
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005944 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005945 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005946 wl->s = strdup(args[1]);
5947 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005948 }
5949 else if (!strcmp(args[0], "errorloc") ||
5950 !strcmp(args[0], "errorloc302") ||
5951 !strcmp(args[0], "errorloc303")) { /* error location */
5952 int errnum, errlen;
5953 char *err;
5954
Willy Tarreau977b8e42006-12-29 14:19:17 +01005955 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005956 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005957
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005959 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005960 err_code |= ERR_ALERT | ERR_FATAL;
5961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005962 }
5963
5964 errnum = atol(args[1]);
5965 if (!strcmp(args[0], "errorloc303")) {
5966 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5967 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5968 } else {
5969 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5970 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5971 }
5972
Willy Tarreau0f772532006-12-23 20:51:41 +01005973 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5974 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005975 chunk_destroy(&curproxy->errmsg[rc]);
5976 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005977 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005979 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005980
5981 if (rc >= HTTP_ERR_SIZE) {
5982 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5983 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 free(err);
5985 }
5986 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005987 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5988 int errnum, errlen, fd;
5989 char *err;
5990 struct stat stat;
5991
5992 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005993 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005994
5995 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005996 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005999 }
6000
6001 fd = open(args[2], O_RDONLY);
6002 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6003 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6004 file, linenum, args[2], args[1]);
6005 if (fd >= 0)
6006 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006007 err_code |= ERR_ALERT | ERR_FATAL;
6008 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006009 }
6010
Willy Tarreau27a674e2009-08-17 07:23:33 +02006011 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006012 errlen = stat.st_size;
6013 } else {
6014 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006015 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006016 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006017 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006018 }
6019
6020 err = malloc(errlen); /* malloc() must succeed during parsing */
6021 errnum = read(fd, err, errlen);
6022 if (errnum != errlen) {
6023 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6024 file, linenum, args[2], args[1]);
6025 close(fd);
6026 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006027 err_code |= ERR_ALERT | ERR_FATAL;
6028 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006029 }
6030 close(fd);
6031
6032 errnum = atol(args[1]);
6033 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6034 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006035 chunk_destroy(&curproxy->errmsg[rc]);
6036 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006037 break;
6038 }
6039 }
6040
6041 if (rc >= HTTP_ERR_SIZE) {
6042 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6043 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006044 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006045 free(err);
6046 }
6047 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006048 else if (!strcmp(args[0], "compression")) {
6049 struct comp *comp;
6050 if (curproxy->comp == NULL) {
6051 comp = calloc(1, sizeof(struct comp));
6052 curproxy->comp = comp;
6053 } else {
6054 comp = curproxy->comp;
6055 }
6056
6057 if (!strcmp(args[1], "algo")) {
6058 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006059 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006060
William Lallemand82fe75c2012-10-23 10:25:10 +02006061 cur_arg = 2;
6062 if (!*args[cur_arg]) {
6063 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6064 file, linenum, args[0]);
6065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
6067 }
6068 while (*(args[cur_arg])) {
6069 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6070 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6071 file, linenum, args[0], args[cur_arg]);
6072 err_code |= ERR_ALERT | ERR_FATAL;
6073 goto out;
6074 }
William Lallemand552df672012-11-07 13:21:47 +01006075 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6076 curproxy->comp->algos->end(&ctx);
6077 } else {
6078 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6079 file, linenum, args[0], args[cur_arg]);
6080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
6082 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006083 cur_arg ++;
6084 continue;
6085 }
6086 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006087 else if (!strcmp(args[1], "offload")) {
6088 comp->offload = 1;
6089 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006090 else if (!strcmp(args[1], "type")) {
6091 int cur_arg;
6092 cur_arg = 2;
6093 if (!*args[cur_arg]) {
6094 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6095 file, linenum, args[0]);
6096 err_code |= ERR_ALERT | ERR_FATAL;
6097 goto out;
6098 }
6099 while (*(args[cur_arg])) {
6100 comp_append_type(comp, args[cur_arg]);
6101 cur_arg ++;
6102 continue;
6103 }
6104 }
6105 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006106 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006107 file, linenum, args[0]);
6108 err_code |= ERR_ALERT | ERR_FATAL;
6109 goto out;
6110 }
6111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006112 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006113 struct cfg_kw_list *kwl;
6114 int index;
6115
6116 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6117 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6118 if (kwl->kw[index].section != CFG_LISTEN)
6119 continue;
6120 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6121 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006122 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006123 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006124 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006125 err_code |= ERR_ALERT | ERR_FATAL;
6126 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006127 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006128 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006129 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006130 err_code |= ERR_WARN;
6131 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006132 }
Willy Tarreau93893792009-07-23 13:19:11 +02006133 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006134 }
6135 }
6136 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006137
Willy Tarreau6daf3432008-01-22 16:44:08 +01006138 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006139 err_code |= ERR_ALERT | ERR_FATAL;
6140 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006141 }
Willy Tarreau93893792009-07-23 13:19:11 +02006142 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006143 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006144 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006145}
6146
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006147int
6148cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6149{
6150
6151 int err_code = 0;
6152 const char *err;
6153
6154 if (!strcmp(args[0], "userlist")) { /* new userlist */
6155 struct userlist *newul;
6156
6157 if (!*args[1]) {
6158 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6159 file, linenum, args[0]);
6160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
6162 }
6163
6164 err = invalid_char(args[1]);
6165 if (err) {
6166 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6167 file, linenum, *err, args[0], args[1]);
6168 err_code |= ERR_ALERT | ERR_FATAL;
6169 goto out;
6170 }
6171
6172 for (newul = userlist; newul; newul = newul->next)
6173 if (!strcmp(newul->name, args[1])) {
6174 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6175 file, linenum, args[1]);
6176 err_code |= ERR_WARN;
6177 goto out;
6178 }
6179
6180 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6181 if (!newul) {
6182 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6183 err_code |= ERR_ALERT | ERR_ABORT;
6184 goto out;
6185 }
6186
6187 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6188 newul->name = strdup(args[1]);
6189
6190 if (!newul->groupusers | !newul->name) {
6191 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6192 err_code |= ERR_ALERT | ERR_ABORT;
6193 goto out;
6194 }
6195
6196 newul->next = userlist;
6197 userlist = newul;
6198
6199 } else if (!strcmp(args[0], "group")) { /* new group */
6200 int cur_arg, i;
6201 const char *err;
6202
6203 if (!*args[1]) {
6204 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6205 file, linenum, args[0]);
6206 err_code |= ERR_ALERT | ERR_FATAL;
6207 goto out;
6208 }
6209
6210 err = invalid_char(args[1]);
6211 if (err) {
6212 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6213 file, linenum, *err, args[0], args[1]);
6214 err_code |= ERR_ALERT | ERR_FATAL;
6215 goto out;
6216 }
6217
6218 for(i = 0; i < userlist->grpcnt; i++)
6219 if (!strcmp(userlist->groups[i], args[1])) {
6220 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6221 file, linenum, args[1], userlist->name);
6222 err_code |= ERR_ALERT;
6223 goto out;
6224 }
6225
6226 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6227 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6228 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6229 err_code |= ERR_ALERT | ERR_FATAL;
6230 goto out;
6231 }
6232
6233 cur_arg = 2;
6234
6235 while (*args[cur_arg]) {
6236 if (!strcmp(args[cur_arg], "users")) {
6237 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6238 cur_arg += 2;
6239 continue;
6240 } else {
6241 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6242 file, linenum, args[0]);
6243 err_code |= ERR_ALERT | ERR_FATAL;
6244 goto out;
6245 }
6246 }
6247
6248 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6249 } else if (!strcmp(args[0], "user")) { /* new user */
6250 struct auth_users *newuser;
6251 int cur_arg;
6252
6253 if (!*args[1]) {
6254 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6255 file, linenum, args[0]);
6256 err_code |= ERR_ALERT | ERR_FATAL;
6257 goto out;
6258 }
6259
6260 for (newuser = userlist->users; newuser; newuser = newuser->next)
6261 if (!strcmp(newuser->user, args[1])) {
6262 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6263 file, linenum, args[1], userlist->name);
6264 err_code |= ERR_ALERT;
6265 goto out;
6266 }
6267
6268 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6269 if (!newuser) {
6270 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6271 err_code |= ERR_ALERT | ERR_ABORT;
6272 goto out;
6273 }
6274
6275 newuser->user = strdup(args[1]);
6276
6277 newuser->next = userlist->users;
6278 userlist->users = newuser;
6279
6280 cur_arg = 2;
6281
6282 while (*args[cur_arg]) {
6283 if (!strcmp(args[cur_arg], "password")) {
6284#ifndef CONFIG_HAP_CRYPT
6285 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6286 file, linenum);
6287 err_code |= ERR_ALERT;
6288#endif
6289 newuser->pass = strdup(args[cur_arg + 1]);
6290 cur_arg += 2;
6291 continue;
6292 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6293 newuser->pass = strdup(args[cur_arg + 1]);
6294 newuser->flags |= AU_O_INSECURE;
6295 cur_arg += 2;
6296 continue;
6297 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006298 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006299 cur_arg += 2;
6300 continue;
6301 } else {
6302 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6303 file, linenum, args[0]);
6304 err_code |= ERR_ALERT | ERR_FATAL;
6305 goto out;
6306 }
6307 }
6308 } else {
6309 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6310 err_code |= ERR_ALERT | ERR_FATAL;
6311 }
6312
6313out:
6314 return err_code;
6315}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316
6317/*
6318 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006319 * Returns the error code, 0 if OK, or any combination of :
6320 * - ERR_ABORT: must abort ASAP
6321 * - ERR_FATAL: we can continue parsing but not start the service
6322 * - ERR_WARN: a warning has been emitted
6323 * - ERR_ALERT: an alert has been emitted
6324 * Only the two first ones can stop processing, the two others are just
6325 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006327int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006329 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 FILE *f;
6331 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006332 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006333 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 if ((f=fopen(file,"r")) == NULL)
6336 return -1;
6337
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006338 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006339 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006340 char *end;
6341 char *args[MAX_LINE_ARGS + 1];
6342 char *line = thisline;
6343
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 linenum++;
6345
6346 end = line + strlen(line);
6347
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006348 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6349 /* Check if we reached the limit and the last char is not \n.
6350 * Watch out for the last line without the terminating '\n'!
6351 */
6352 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006353 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006354 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006355 }
6356
Willy Tarreaubaaee002006-06-26 02:48:02 +02006357 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006358 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006359 line++;
6360
6361 arg = 0;
6362 args[arg] = line;
6363
6364 while (*line && arg < MAX_LINE_ARGS) {
6365 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6366 * C equivalent value. Other combinations left unchanged (eg: \1).
6367 */
6368 if (*line == '\\') {
6369 int skip = 0;
6370 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6371 *line = line[1];
6372 skip = 1;
6373 }
6374 else if (line[1] == 'r') {
6375 *line = '\r';
6376 skip = 1;
6377 }
6378 else if (line[1] == 'n') {
6379 *line = '\n';
6380 skip = 1;
6381 }
6382 else if (line[1] == 't') {
6383 *line = '\t';
6384 skip = 1;
6385 }
6386 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006387 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 unsigned char hex1, hex2;
6389 hex1 = toupper(line[2]) - '0';
6390 hex2 = toupper(line[3]) - '0';
6391 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6392 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6393 *line = (hex1<<4) + hex2;
6394 skip = 3;
6395 }
6396 else {
6397 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006398 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 }
6400 }
6401 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006402 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006403 end -= skip;
6404 }
6405 line++;
6406 }
6407 else if (*line == '#' || *line == '\n' || *line == '\r') {
6408 /* end of string, end of loop */
6409 *line = 0;
6410 break;
6411 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006412 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006414 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006415 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 line++;
6417 args[++arg] = line;
6418 }
6419 else {
6420 line++;
6421 }
6422 }
6423
6424 /* empty line */
6425 if (!**args)
6426 continue;
6427
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006428 if (*line) {
6429 /* we had to stop due to too many args.
6430 * Let's terminate the string, print the offending part then cut the
6431 * last arg.
6432 */
6433 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6434 line++;
6435 *line = '\0';
6436
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006437 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006438 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006439 err_code |= ERR_ALERT | ERR_FATAL;
6440 args[arg] = line;
6441 }
6442
Willy Tarreau540abe42007-05-02 20:50:16 +02006443 /* zero out remaining args and ensure that at least one entry
6444 * is zeroed out.
6445 */
6446 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006447 args[arg] = line;
6448 }
6449
Willy Tarreau3842f002009-06-14 11:39:52 +02006450 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006451 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006452 char *tmp;
6453
Willy Tarreau3842f002009-06-14 11:39:52 +02006454 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006455 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006456 for (arg=0; *args[arg+1]; arg++)
6457 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006458 *tmp = '\0'; // fix the next arg to \0
6459 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006460 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006461 else if (!strcmp(args[0], "default")) {
6462 kwm = KWM_DEF;
6463 for (arg=0; *args[arg+1]; arg++)
6464 args[arg] = args[arg+1]; // shift args after inversion
6465 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006466
William Lallemand0f99e342011-10-12 17:50:54 +02006467 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6468 strcmp(args[0], "log") != 0) {
6469 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006470 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006471 }
6472
Willy Tarreau977b8e42006-12-29 14:19:17 +01006473 if (!strcmp(args[0], "listen") ||
6474 !strcmp(args[0], "frontend") ||
6475 !strcmp(args[0], "backend") ||
6476 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006477 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006479 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006480 cursection = strdup(args[0]);
6481 }
6482 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006484 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006485 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006486 }
6487 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006488 confsect = CFG_USERLIST;
6489 free(cursection);
6490 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006491 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006492 else if (!strcmp(args[0], "peers")) {
6493 confsect = CFG_PEERS;
6494 free(cursection);
6495 cursection = strdup(args[0]);
6496 }
6497
Willy Tarreaubaaee002006-06-26 02:48:02 +02006498 /* else it's a section keyword */
6499
6500 switch (confsect) {
6501 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006502 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 break;
6504 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006505 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006507 case CFG_USERLIST:
6508 err_code |= cfg_parse_users(file, linenum, args, kwm);
6509 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006510 case CFG_PEERS:
6511 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6512 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006514 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006515 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006516 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006517
6518 if (err_code & ERR_ABORT)
6519 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006521 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006522 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006524 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006525}
6526
Willy Tarreaubb925012009-07-23 13:36:36 +02006527/*
6528 * Returns the error code, 0 if OK, or any combination of :
6529 * - ERR_ABORT: must abort ASAP
6530 * - ERR_FATAL: we can continue parsing but not start the service
6531 * - ERR_WARN: a warning has been emitted
6532 * - ERR_ALERT: an alert has been emitted
6533 * Only the two first ones can stop processing, the two others are just
6534 * indicators.
6535 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006536int check_config_validity()
6537{
6538 int cfgerr = 0;
6539 struct proxy *curproxy = NULL;
6540 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006541 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006542 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006543 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006544 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006546 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 /*
6548 * Now, check for the integrity of all that we have collected.
6549 */
6550
6551 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006552 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006553
Willy Tarreau193b8c62012-11-22 00:17:38 +01006554 if (!global.tune.max_http_hdr)
6555 global.tune.max_http_hdr = MAX_HTTP_HDR;
6556
6557 if (!global.tune.cookie_len)
6558 global.tune.cookie_len = CAPTURE_LEN;
6559
6560 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6561
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006562 /* first, we will invert the proxy list order */
6563 curproxy = NULL;
6564 while (proxy) {
6565 struct proxy *next;
6566
6567 next = proxy->next;
6568 proxy->next = curproxy;
6569 curproxy = proxy;
6570 if (!next)
6571 break;
6572 proxy = next;
6573 }
6574
Willy Tarreaubaaee002006-06-26 02:48:02 +02006575 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006576 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006577 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006578 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006579 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006580 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006581 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006582 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006583
Willy Tarreau050536d2012-10-04 08:47:34 +02006584 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006585 /* proxy ID not set, use automatic numbering with first
6586 * spare entry starting with next_pxid.
6587 */
6588 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6589 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6590 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006591 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006592 next_pxid++;
6593
Willy Tarreau55ea7572007-06-17 19:56:27 +02006594
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006596 /* ensure we don't keep listeners uselessly bound */
6597 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006598 curproxy = curproxy->next;
6599 continue;
6600 }
6601
Willy Tarreau16a21472012-11-19 12:39:59 +01006602 /* number of processes this proxy is bound to */
6603 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6604
Willy Tarreauff01a212009-03-15 13:46:16 +01006605 switch (curproxy->mode) {
6606 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006607 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006608 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006609 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6610 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006611 cfgerr++;
6612 }
6613
6614 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006615 Warning("config : servers will be ignored for %s '%s'.\n",
6616 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006617 break;
6618
6619 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006620 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006621 break;
6622
6623 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006624 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006625 break;
6626 }
6627
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006628 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006629 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006630 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006631 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6632 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006633 cfgerr++;
6634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006635#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006636 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006637 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6638 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006639 cfgerr++;
6640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006641#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006642 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006643 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6644 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006645 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006646 }
6647 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006648 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006649 /* If no LB algo is set in a backend, and we're not in
6650 * transparent mode, dispatch mode nor proxy mode, we
6651 * want to use balance roundrobin by default.
6652 */
6653 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6654 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006655 }
6656 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006657
Willy Tarreau1620ec32011-08-06 17:05:02 +02006658 if (curproxy->options & PR_O_DISPATCH)
6659 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6660 else if (curproxy->options & PR_O_HTTP_PROXY)
6661 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6662 else if (curproxy->options & PR_O_TRANSP)
6663 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006664
Willy Tarreau1620ec32011-08-06 17:05:02 +02006665 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6666 if (curproxy->options & PR_O_DISABLE404) {
6667 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6668 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6669 err_code |= ERR_WARN;
6670 curproxy->options &= ~PR_O_DISABLE404;
6671 }
6672 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6673 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6674 "send-state", proxy_type_str(curproxy), curproxy->id);
6675 err_code |= ERR_WARN;
6676 curproxy->options &= ~PR_O2_CHK_SNDST;
6677 }
Willy Tarreauef781042010-01-27 11:53:01 +01006678 }
6679
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006680 /* if a default backend was specified, let's find it */
6681 if (curproxy->defbe.name) {
6682 struct proxy *target;
6683
Alex Williams96532db2009-11-01 21:27:13 -05006684 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006685 if (!target) {
6686 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6687 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006688 cfgerr++;
6689 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006690 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6691 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006692 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006693 } else {
6694 free(curproxy->defbe.name);
6695 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006696 /* we force the backend to be present on at least all of
6697 * the frontend's processes.
6698 */
6699 target->bind_proc = curproxy->bind_proc ?
6700 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006701
6702 /* Emit a warning if this proxy also has some servers */
6703 if (curproxy->srv) {
6704 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6705 curproxy->id);
6706 err_code |= ERR_WARN;
6707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006708 }
6709 }
6710
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006711 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006712 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6713 /* map jump target for ACT_SETBE in req_rep chain */
6714 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006715 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006716 struct proxy *target;
6717
Willy Tarreaua496b602006-12-17 23:15:24 +01006718 if (exp->action != ACT_SETBE)
6719 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006720
Alex Williams96532db2009-11-01 21:27:13 -05006721 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006722 if (!target) {
6723 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6724 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006725 cfgerr++;
6726 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006727 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6728 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006729 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006730 } else {
6731 free((void *)exp->replace);
6732 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006733 /* we force the backend to be present on at least all of
6734 * the frontend's processes.
6735 */
6736 target->bind_proc = curproxy->bind_proc ?
6737 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006738 }
6739 }
6740 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006741
6742 /* find the target proxy for 'use_backend' rules */
6743 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006744 struct proxy *target;
6745
Alex Williams96532db2009-11-01 21:27:13 -05006746 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006747
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006748 if (!target) {
6749 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6750 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006751 cfgerr++;
6752 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006753 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6754 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006755 cfgerr++;
6756 } else {
6757 free((void *)rule->be.name);
6758 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006759 /* we force the backend to be present on at least all of
6760 * the frontend's processes.
6761 */
6762 target->bind_proc = curproxy->bind_proc ?
6763 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006764 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006765 }
6766
6767 /* find the target proxy for 'use_backend' rules */
6768 list_for_each_entry(srule, &curproxy->server_rules, list) {
6769 struct server *target = findserver(curproxy, srule->srv.name);
6770
6771 if (!target) {
6772 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6773 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6774 cfgerr++;
6775 continue;
6776 }
6777 free((void *)srule->srv.name);
6778 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006779 }
6780
Emeric Brunb982a3d2010-01-04 15:45:53 +01006781 /* find the target table for 'stick' rules */
6782 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6783 struct proxy *target;
6784
Emeric Brun1d33b292010-01-04 15:47:17 +01006785 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6786 if (mrule->flags & STK_IS_STORE)
6787 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6788
Emeric Brunb982a3d2010-01-04 15:45:53 +01006789 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006790 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006791 else
6792 target = curproxy;
6793
6794 if (!target) {
6795 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6796 curproxy->id, mrule->table.name);
6797 cfgerr++;
6798 }
6799 else if (target->table.size == 0) {
6800 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6801 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6802 cfgerr++;
6803 }
Willy Tarreau12785782012-04-27 21:37:17 +02006804 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6805 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006806 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6807 cfgerr++;
6808 }
6809 else {
6810 free((void *)mrule->table.name);
6811 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006812 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006813 }
6814 }
6815
6816 /* find the target table for 'store response' rules */
6817 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6818 struct proxy *target;
6819
Emeric Brun1d33b292010-01-04 15:47:17 +01006820 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6821
Emeric Brunb982a3d2010-01-04 15:45:53 +01006822 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006823 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006824 else
6825 target = curproxy;
6826
6827 if (!target) {
6828 Alert("Proxy '%s': unable to find store table '%s'.\n",
6829 curproxy->id, mrule->table.name);
6830 cfgerr++;
6831 }
6832 else if (target->table.size == 0) {
6833 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6834 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6835 cfgerr++;
6836 }
Willy Tarreau12785782012-04-27 21:37:17 +02006837 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6838 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006839 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6840 cfgerr++;
6841 }
6842 else {
6843 free((void *)mrule->table.name);
6844 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006845 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006846 }
6847 }
6848
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006849 /* find the target table for 'tcp-request' layer 4 rules */
6850 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6851 struct proxy *target;
6852
Willy Tarreaub4c84932013-07-23 19:15:30 +02006853 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006854 continue;
6855
6856 if (trule->act_prm.trk_ctr.table.n)
6857 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6858 else
6859 target = curproxy;
6860
6861 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006862 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6863 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006864 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006865 cfgerr++;
6866 }
6867 else if (target->table.size == 0) {
6868 Alert("Proxy '%s': table '%s' used but not configured.\n",
6869 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6870 cfgerr++;
6871 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006872 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6873 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6874 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 +01006875 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006876 cfgerr++;
6877 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006878 else {
6879 free(trule->act_prm.trk_ctr.table.n);
6880 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006881 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006882 * to pass a list of counters to track and allocate them right here using
6883 * stktable_alloc_data_type().
6884 */
6885 }
6886 }
6887
Willy Tarreaud1f96522010-08-03 19:34:32 +02006888 /* find the target table for 'tcp-request' layer 6 rules */
6889 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6890 struct proxy *target;
6891
Willy Tarreaub4c84932013-07-23 19:15:30 +02006892 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006893 continue;
6894
6895 if (trule->act_prm.trk_ctr.table.n)
6896 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6897 else
6898 target = curproxy;
6899
6900 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006901 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6902 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006903 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006904 cfgerr++;
6905 }
6906 else if (target->table.size == 0) {
6907 Alert("Proxy '%s': table '%s' used but not configured.\n",
6908 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6909 cfgerr++;
6910 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006911 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6912 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6913 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 +01006914 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006915 cfgerr++;
6916 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006917 else {
6918 free(trule->act_prm.trk_ctr.table.n);
6919 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006920 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006921 * to pass a list of counters to track and allocate them right here using
6922 * stktable_alloc_data_type().
6923 */
6924 }
6925 }
6926
Emeric Brun32da3c42010-09-23 18:39:19 +02006927 if (curproxy->table.peers.name) {
6928 struct peers *curpeers = peers;
6929
6930 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6931 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6932 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006933 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006934 break;
6935 }
6936 }
6937
6938 if (!curpeers) {
6939 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6940 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006941 free((void *)curproxy->table.peers.name);
6942 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006943 cfgerr++;
6944 }
6945 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006946 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6947 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006948 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006949 cfgerr++;
6950 }
6951 }
6952
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006953 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006954 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006955 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6956 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6957 "proxy", curproxy->id);
6958 cfgerr++;
6959 goto out_uri_auth_compat;
6960 }
6961
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006962 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006963 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006964 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006965 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006966
Willy Tarreau95fa4692010-02-01 13:05:50 +01006967 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6968 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006969
6970 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006971 uri_auth_compat_req[i++] = "realm";
6972 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6973 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006974
Willy Tarreau95fa4692010-02-01 13:05:50 +01006975 uri_auth_compat_req[i++] = "unless";
6976 uri_auth_compat_req[i++] = "{";
6977 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6978 uri_auth_compat_req[i++] = "}";
6979 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006980
Willy Tarreauff011f22011-01-06 17:51:27 +01006981 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6982 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006983 cfgerr++;
6984 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006985 }
6986
Willy Tarreauff011f22011-01-06 17:51:27 +01006987 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006988
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006989 if (curproxy->uri_auth->auth_realm) {
6990 free(curproxy->uri_auth->auth_realm);
6991 curproxy->uri_auth->auth_realm = NULL;
6992 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006993
6994 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006995 }
6996out_uri_auth_compat:
6997
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006998 /* compile the log format */
6999 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007000 if (curproxy->conf.logformat_string != default_http_log_format &&
7001 curproxy->conf.logformat_string != default_tcp_log_format &&
7002 curproxy->conf.logformat_string != clf_http_log_format)
7003 free(curproxy->conf.logformat_string);
7004 curproxy->conf.logformat_string = NULL;
7005 free(curproxy->conf.lfs_file);
7006 curproxy->conf.lfs_file = NULL;
7007 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007008 }
7009
Willy Tarreau62a61232013-04-12 18:13:46 +02007010 if (curproxy->conf.logformat_string) {
7011 curproxy->conf.args.ctx = ARGC_LOG;
7012 curproxy->conf.args.file = curproxy->conf.lfs_file;
7013 curproxy->conf.args.line = curproxy->conf.lfs_line;
7014 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007015 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02007016 curproxy->conf.args.file = NULL;
7017 curproxy->conf.args.line = 0;
7018 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007019
Willy Tarreau62a61232013-04-12 18:13:46 +02007020 if (curproxy->conf.uniqueid_format_string) {
7021 curproxy->conf.args.ctx = ARGC_UIF;
7022 curproxy->conf.args.file = curproxy->conf.uif_file;
7023 curproxy->conf.args.line = curproxy->conf.uif_line;
7024 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007025 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02007026 curproxy->conf.args.file = NULL;
7027 curproxy->conf.args.line = 0;
7028 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007029
7030 /* only now we can check if some args remain unresolved */
7031 cfgerr += smp_resolve_args(curproxy);
7032 if (!cfgerr)
7033 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007034
Willy Tarreau2738a142006-07-08 17:28:09 +02007035 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007036 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007037 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007038 (!curproxy->timeout.connect ||
7039 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007040 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007041 " | While not properly invalid, you will certainly encounter various problems\n"
7042 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007043 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007044 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007045 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007046 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007047
Willy Tarreau1fa31262007-12-03 00:36:16 +01007048 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7049 * We must still support older configurations, so let's find out whether those
7050 * parameters have been set or must be copied from contimeouts.
7051 */
7052 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007053 if (!curproxy->timeout.tarpit ||
7054 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007055 /* tarpit timeout not set. We search in the following order:
7056 * default.tarpit, curr.connect, default.connect.
7057 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007058 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007059 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007060 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007061 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007062 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007063 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007064 }
7065 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007066 (!curproxy->timeout.queue ||
7067 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007068 /* queue timeout not set. We search in the following order:
7069 * default.queue, curr.connect, default.connect.
7070 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007071 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007072 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007073 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007074 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007075 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007076 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007077 }
7078 }
7079
Willy Tarreau1620ec32011-08-06 17:05:02 +02007080 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007081 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7082 curproxy->check_req = (char *)malloc(curproxy->check_len);
7083 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007084 }
7085
Willy Tarreau193b8c62012-11-22 00:17:38 +01007086 /* ensure that cookie capture length is not too large */
7087 if (curproxy->capture_len >= global.tune.cookie_len) {
7088 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7089 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7090 err_code |= ERR_WARN;
7091 curproxy->capture_len = global.tune.cookie_len - 1;
7092 }
7093
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007094 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007095 if (curproxy->nb_req_cap) {
7096 if (curproxy->mode == PR_MODE_HTTP) {
7097 curproxy->req_cap_pool = create_pool("ptrcap",
7098 curproxy->nb_req_cap * sizeof(char *),
7099 MEM_F_SHARED);
7100 } else {
7101 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7102 proxy_type_str(curproxy), curproxy->id);
7103 err_code |= ERR_WARN;
7104 curproxy->to_log &= ~LW_REQHDR;
7105 curproxy->nb_req_cap = 0;
7106 }
7107 }
7108
7109 if (curproxy->nb_rsp_cap) {
7110 if (curproxy->mode == PR_MODE_HTTP) {
7111 curproxy->rsp_cap_pool = create_pool("ptrcap",
7112 curproxy->nb_rsp_cap * sizeof(char *),
7113 MEM_F_SHARED);
7114 } else {
7115 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7116 proxy_type_str(curproxy), curproxy->id);
7117 err_code |= ERR_WARN;
7118 curproxy->to_log &= ~LW_REQHDR;
7119 curproxy->nb_rsp_cap = 0;
7120 }
7121 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007122
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123 /* first, we will invert the servers list order */
7124 newsrv = NULL;
7125 while (curproxy->srv) {
7126 struct server *next;
7127
7128 next = curproxy->srv->next;
7129 curproxy->srv->next = newsrv;
7130 newsrv = curproxy->srv;
7131 if (!next)
7132 break;
7133 curproxy->srv = next;
7134 }
7135
Willy Tarreau17edc812014-01-03 12:14:34 +01007136 /* Check that no server name conflicts. This causes trouble in the stats.
7137 * We only emit a warning for the first conflict affecting each server,
7138 * in order to avoid combinatory explosion if all servers have the same
7139 * name. We do that only for servers which do not have an explicit ID,
7140 * because these IDs were made also for distinguishing them and we don't
7141 * want to annoy people who correctly manage them.
7142 */
7143 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7144 struct server *other_srv;
7145
7146 if (newsrv->puid)
7147 continue;
7148
7149 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7150 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7151 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7152 newsrv->conf.file, newsrv->conf.line,
7153 proxy_type_str(curproxy), curproxy->id,
7154 newsrv->id, other_srv->conf.line);
7155 break;
7156 }
7157 }
7158 }
7159
Willy Tarreaudd701652010-05-25 23:03:02 +02007160 /* assign automatic UIDs to servers which don't have one yet */
7161 next_id = 1;
7162 newsrv = curproxy->srv;
7163 while (newsrv != NULL) {
7164 if (!newsrv->puid) {
7165 /* server ID not set, use automatic numbering with first
7166 * spare entry starting with next_svid.
7167 */
7168 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7169 newsrv->conf.id.key = newsrv->puid = next_id;
7170 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7171 }
7172 next_id++;
7173 newsrv = newsrv->next;
7174 }
7175
Willy Tarreau20697042007-11-15 23:26:18 +01007176 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007177 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007178
Willy Tarreau62c3be22012-01-20 13:12:32 +01007179 /*
7180 * If this server supports a maxconn parameter, it needs a dedicated
7181 * tasks to fill the emptied slots when a connection leaves.
7182 * Also, resolve deferred tracking dependency if needed.
7183 */
7184 newsrv = curproxy->srv;
7185 while (newsrv != NULL) {
7186 if (newsrv->minconn > newsrv->maxconn) {
7187 /* Only 'minconn' was specified, or it was higher than or equal
7188 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7189 * this will avoid further useless expensive computations.
7190 */
7191 newsrv->maxconn = newsrv->minconn;
7192 } else if (newsrv->maxconn && !newsrv->minconn) {
7193 /* minconn was not specified, so we set it to maxconn */
7194 newsrv->minconn = newsrv->maxconn;
7195 }
7196
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007197#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007198 if (newsrv->use_ssl || newsrv->check.use_ssl)
7199 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007200#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007201
Willy Tarreau2f075e92013-12-03 11:11:34 +01007202 /* set the check type on the server */
7203 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7204
Willy Tarreau62c3be22012-01-20 13:12:32 +01007205 if (newsrv->trackit) {
7206 struct proxy *px;
7207 struct server *srv;
7208 char *pname, *sname;
7209
7210 pname = newsrv->trackit;
7211 sname = strrchr(pname, '/');
7212
7213 if (sname)
7214 *sname++ = '\0';
7215 else {
7216 sname = pname;
7217 pname = NULL;
7218 }
7219
7220 if (pname) {
7221 px = findproxy(pname, PR_CAP_BE);
7222 if (!px) {
7223 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7224 proxy_type_str(curproxy), curproxy->id,
7225 newsrv->id, pname);
7226 cfgerr++;
7227 goto next_srv;
7228 }
7229 } else
7230 px = curproxy;
7231
7232 srv = findserver(px, sname);
7233 if (!srv) {
7234 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7235 proxy_type_str(curproxy), curproxy->id,
7236 newsrv->id, sname);
7237 cfgerr++;
7238 goto next_srv;
7239 }
7240
Willy Tarreauff5ae352013-12-11 20:36:34 +01007241 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007242 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7243 "tracking as it does not have checks enabled.\n",
7244 proxy_type_str(curproxy), curproxy->id,
7245 newsrv->id, px->id, srv->id);
7246 cfgerr++;
7247 goto next_srv;
7248 }
7249
7250 if (curproxy != px &&
7251 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7252 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7253 "tracking: disable-on-404 option inconsistency.\n",
7254 proxy_type_str(curproxy), curproxy->id,
7255 newsrv->id, px->id, srv->id);
7256 cfgerr++;
7257 goto next_srv;
7258 }
7259
7260 /* if the other server is forced disabled, we have to do the same here */
7261 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007262 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007263 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007264 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007265 }
7266
7267 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007268 newsrv->tracknext = srv->trackers;
7269 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007270
7271 free(newsrv->trackit);
7272 newsrv->trackit = NULL;
7273 }
7274 next_srv:
7275 newsrv = newsrv->next;
7276 }
7277
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007278 /* We have to initialize the server lookup mechanism depending
7279 * on what LB algorithm was choosen.
7280 */
7281
7282 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7283 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7284 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007285 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7286 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7287 init_server_map(curproxy);
7288 } else {
7289 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7290 fwrr_init_server_groups(curproxy);
7291 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007292 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007293
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007294 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007295 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7296 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7297 fwlc_init_server_tree(curproxy);
7298 } else {
7299 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7300 fas_init_server_tree(curproxy);
7301 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007302 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007303
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007304 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007305 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7306 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7307 chash_init_server_tree(curproxy);
7308 } else {
7309 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7310 init_server_map(curproxy);
7311 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007312 break;
7313 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007314
7315 if (curproxy->options & PR_O_LOGASAP)
7316 curproxy->to_log &= ~LW_BYTES;
7317
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007318 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007319 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007320 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7321 proxy_type_str(curproxy), curproxy->id);
7322 err_code |= ERR_WARN;
7323 }
7324
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007325 if (curproxy->mode != PR_MODE_HTTP) {
7326 int optnum;
7327
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007328 if (curproxy->uri_auth) {
7329 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7330 proxy_type_str(curproxy), curproxy->id);
7331 err_code |= ERR_WARN;
7332 curproxy->uri_auth = NULL;
7333 }
7334
Willy Tarreau87cf5142011-08-19 22:57:24 +02007335 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007336 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7337 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7338 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007339 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007340 }
7341
7342 if (curproxy->options & PR_O_ORGTO) {
7343 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7344 "originalto", proxy_type_str(curproxy), curproxy->id);
7345 err_code |= ERR_WARN;
7346 curproxy->options &= ~PR_O_ORGTO;
7347 }
7348
7349 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7350 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7351 (curproxy->cap & cfg_opts[optnum].cap) &&
7352 (curproxy->options & cfg_opts[optnum].val)) {
7353 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7354 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7355 err_code |= ERR_WARN;
7356 curproxy->options &= ~cfg_opts[optnum].val;
7357 }
7358 }
7359
7360 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7361 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7362 (curproxy->cap & cfg_opts2[optnum].cap) &&
7363 (curproxy->options2 & cfg_opts2[optnum].val)) {
7364 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7365 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7366 err_code |= ERR_WARN;
7367 curproxy->options2 &= ~cfg_opts2[optnum].val;
7368 }
7369 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007370
Pieter Baauwd551fb52013-05-08 22:49:23 +02007371#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007372 if (curproxy->conn_src.bind_hdr_occ) {
7373 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007374 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007375 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007376 err_code |= ERR_WARN;
7377 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007378#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007379 }
7380
Willy Tarreaubaaee002006-06-26 02:48:02 +02007381 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007382 * ensure that we're not cross-dressing a TCP server into HTTP.
7383 */
7384 newsrv = curproxy->srv;
7385 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007386 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007387 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7388 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007389 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007390 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007391
Willy Tarreau0cec3312011-10-31 13:49:26 +01007392 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7393 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7394 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7395 err_code |= ERR_WARN;
7396 }
7397
Willy Tarreau82ffa392013-08-13 17:19:08 +02007398 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7399 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7400 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7401 err_code |= ERR_WARN;
7402 }
7403
Pieter Baauwd551fb52013-05-08 22:49:23 +02007404#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007405 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7406 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007407 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 +01007408 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007409 err_code |= ERR_WARN;
7410 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007411#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007412 newsrv = newsrv->next;
7413 }
7414
Willy Tarreauc1a21672009-08-16 22:37:44 +02007415 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007416 if (!curproxy->accept)
7417 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007418
Willy Tarreauc1a21672009-08-16 22:37:44 +02007419 if (curproxy->tcp_req.inspect_delay ||
7420 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007421 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007422
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007423 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007424 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007425 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007426 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007427
7428 /* both TCP and HTTP must check switching rules */
7429 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7430 }
7431
7432 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007433 if (curproxy->tcp_req.inspect_delay ||
7434 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7435 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7436
Emeric Brun97679e72010-09-23 17:56:44 +02007437 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7438 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7439
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007440 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007441 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007442 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007443 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007444
7445 /* If the backend does requires RDP cookie persistence, we have to
7446 * enable the corresponding analyser.
7447 */
7448 if (curproxy->options2 & PR_O2_RDPC_PRST)
7449 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7450 }
7451
Emeric Brunc52962f2012-11-15 18:28:02 +01007452#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007453 /* Configure SSL for each bind line.
7454 * Note: if configuration fails at some point, the ->ctx member
7455 * remains NULL so that listeners can later detach.
7456 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007457 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007458 if (!bind_conf->is_ssl) {
7459 if (bind_conf->default_ctx) {
7460 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7461 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7462 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007463 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007464 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007465 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007466 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007467 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007468 cfgerr++;
7469 continue;
7470 }
7471
Emeric Brun4b3091e2012-09-24 15:48:52 +02007472 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007473 Alert("Unable to allocate SSL session cache.\n");
7474 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007475 continue;
7476 }
7477
Emeric Brunfc0421f2012-09-07 17:30:07 +02007478 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007479 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007480 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007481#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007482
Willy Tarreaue6b98942007-10-29 01:09:36 +01007483 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007484 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007485 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007486 if (!listener->luid) {
7487 /* listener ID not set, use automatic numbering with first
7488 * spare entry starting with next_luid.
7489 */
7490 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7491 listener->conf.id.key = listener->luid = next_id;
7492 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007493 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007494 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007495
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007496 /* enable separate counters */
7497 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7498 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007499 if (!listener->name)
7500 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007501 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007502
Willy Tarreaue6b98942007-10-29 01:09:36 +01007503 if (curproxy->options & PR_O_TCP_NOLING)
7504 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007505 if (!listener->maxconn)
7506 listener->maxconn = curproxy->maxconn;
7507 if (!listener->backlog)
7508 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007509 if (!listener->maxaccept)
7510 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7511
7512 /* we want to have an optimal behaviour on single process mode to
7513 * maximize the work at once, but in multi-process we want to keep
7514 * some fairness between processes, so we target half of the max
7515 * number of events to be balanced over all the processes the proxy
7516 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7517 * used to disable the limit.
7518 */
7519 if (listener->maxaccept > 0) {
7520 if (nbproc > 1)
7521 listener->maxaccept = (listener->maxaccept + 1) / 2;
7522 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7523 }
7524
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007525 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007526 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007527 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007528 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007529
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007530 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7531 listener->options |= LI_O_TCP_RULES;
7532
Willy Tarreaude3041d2010-05-31 10:56:17 +02007533 if (curproxy->mon_mask.s_addr)
7534 listener->options |= LI_O_CHK_MONNET;
7535
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007536 /* smart accept mode is automatic in HTTP mode */
7537 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007538 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007539 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7540 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007541 }
7542
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007543 /* Release unused SSL configs */
7544 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7545 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007546 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007547#ifdef USE_OPENSSL
7548 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007549 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007550 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007551 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007552 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007553#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007554 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007555
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007556 /* Check multi-process mode compatibility for the current proxy */
7557 if (global.nbproc > 1) {
7558 int nbproc = 0;
7559 if (curproxy->bind_proc) {
7560 int proc;
7561 for (proc = 0; proc < global.nbproc; proc++) {
7562 if (curproxy->bind_proc & (1 << proc)) {
7563 nbproc++;
7564 }
7565 }
7566 } else {
7567 nbproc = global.nbproc;
7568 }
7569 if (curproxy->table.peers.name) {
7570 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7571 curproxy->id);
7572 cfgerr++;
7573 }
7574 if (nbproc > 1) {
7575 if (curproxy->uri_auth) {
7576 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7577 curproxy->id);
7578 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7579 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7580 curproxy->id);
7581 }
7582 }
7583 if (curproxy->appsession_name) {
7584 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7585 curproxy->id);
7586 }
7587 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7588 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7589 curproxy->id);
7590 }
7591 }
7592 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007593
7594 /* create the task associated with the proxy */
7595 curproxy->task = task_new();
7596 if (curproxy->task) {
7597 curproxy->task->context = curproxy;
7598 curproxy->task->process = manage_proxy;
7599 /* no need to queue, it will be done automatically if some
7600 * listener gets limited.
7601 */
7602 curproxy->task->expire = TICK_ETERNITY;
7603 } else {
7604 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7605 curproxy->id);
7606 cfgerr++;
7607 }
7608
Willy Tarreaubaaee002006-06-26 02:48:02 +02007609 curproxy = curproxy->next;
7610 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007611
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007612 /* Check multi-process mode compatibility */
7613 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007614 if (global.stats_fe && !global.stats_fe->bind_proc) {
7615 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 +01007616 }
7617 }
7618
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007619 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7620 struct auth_users *curuser;
7621 int g;
7622
7623 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7624 unsigned int group_mask = 0;
7625 char *group = NULL;
7626
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007627 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007628 continue;
7629
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007630 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007631
7632 for (g = 0; g < curuserlist->grpcnt; g++)
7633 if (!strcmp(curuserlist->groups[g], group))
7634 break;
7635
7636 if (g == curuserlist->grpcnt) {
7637 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7638 curuserlist->name, group, curuser->user);
7639 err_code |= ERR_ALERT | ERR_FATAL;
7640 goto out;
7641 }
7642
7643 group_mask |= (1 << g);
7644 }
7645
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007646 free(curuser->u.groups);
7647 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007648 }
7649
7650 for (g = 0; g < curuserlist->grpcnt; g++) {
7651 char *user = NULL;
7652
7653 if (!curuserlist->groupusers[g])
7654 continue;
7655
7656 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7657 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7658 if (!strcmp(curuser->user, user))
7659 break;
7660
7661 if (!curuser) {
7662 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7663 curuserlist->name, user, curuserlist->groups[g]);
7664 err_code |= ERR_ALERT | ERR_FATAL;
7665 goto out;
7666 }
7667
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007668 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007669 }
7670
7671 free(curuserlist->groupusers[g]);
7672 }
7673
7674 free(curuserlist->groupusers);
7675
7676#ifdef DEBUG_AUTH
7677 for (g = 0; g < curuserlist->grpcnt; g++) {
7678 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7679
7680 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007681 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007682 fprintf(stderr, " %s", curuser->user);
7683 }
7684
7685 fprintf(stderr, "\n");
7686 }
7687#endif
7688
Willy Tarreaufbb78422011-06-05 15:38:35 +02007689 }
7690
7691 /* automatically compute fullconn if not set. We must not do it in the
7692 * loop above because cross-references are not yet fully resolved.
7693 */
7694 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7695 /* If <fullconn> is not set, let's set it to 10% of the sum of
7696 * the possible incoming frontend's maxconns.
7697 */
7698 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7699 struct proxy *fe;
7700 int total = 0;
7701
7702 /* sum up the number of maxconns of frontends which
7703 * reference this backend at least once or which are
7704 * the same one ('listen').
7705 */
7706 for (fe = proxy; fe; fe = fe->next) {
7707 struct switching_rule *rule;
7708 struct hdr_exp *exp;
7709 int found = 0;
7710
7711 if (!(fe->cap & PR_CAP_FE))
7712 continue;
7713
7714 if (fe == curproxy) /* we're on a "listen" instance */
7715 found = 1;
7716
7717 if (fe->defbe.be == curproxy) /* "default_backend" */
7718 found = 1;
7719
7720 /* check if a "use_backend" rule matches */
7721 if (!found) {
7722 list_for_each_entry(rule, &fe->switching_rules, list) {
7723 if (rule->be.backend == curproxy) {
7724 found = 1;
7725 break;
7726 }
7727 }
7728 }
7729
7730 /* check if a "reqsetbe" rule matches */
7731 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7732 if (exp->action == ACT_SETBE &&
7733 (struct proxy *)exp->replace == curproxy) {
7734 found = 1;
7735 break;
7736 }
7737 }
7738
7739 /* now we've checked all possible ways to reference a backend
7740 * from a frontend.
7741 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007742 if (!found)
7743 continue;
7744 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007745 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007746 /* we have the sum of the maxconns in <total>. We only
7747 * keep 10% of that sum to set the default fullconn, with
7748 * a hard minimum of 1 (to avoid a divide by zero).
7749 */
7750 curproxy->fullconn = (total + 9) / 10;
7751 if (!curproxy->fullconn)
7752 curproxy->fullconn = 1;
7753 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007754 }
7755
Willy Tarreau056f5682010-06-06 15:51:11 +02007756 /* initialize stick-tables on backend capable proxies. This must not
7757 * be done earlier because the data size may be discovered while parsing
7758 * other proxies.
7759 */
Godbach9703e662013-12-11 21:11:41 +08007760 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7761 if (!stktable_init(&curproxy->table)) {
7762 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7763 cfgerr++;
7764 }
7765 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007766
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007767 /*
7768 * Recount currently required checks.
7769 */
7770
7771 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7772 int optnum;
7773
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007774 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7775 if (curproxy->options & cfg_opts[optnum].val)
7776 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007777
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007778 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7779 if (curproxy->options2 & cfg_opts2[optnum].val)
7780 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007781 }
7782
Willy Tarreau122541c2011-09-07 21:24:49 +02007783 if (peers) {
7784 struct peers *curpeers = peers, **last;
7785 struct peer *p, *pb;
7786
7787 /* Remove all peers sections which don't have a valid listener.
7788 * This can happen when a peers section is never referenced and
7789 * does not contain a local peer.
7790 */
7791 last = &peers;
7792 while (*last) {
7793 curpeers = *last;
7794 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007795 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007796 last = &curpeers->next;
7797 continue;
7798 }
7799
7800 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7801 curpeers->id, localpeer);
7802
7803 p = curpeers->remote;
7804 while (p) {
7805 pb = p->next;
7806 free(p->id);
7807 free(p);
7808 p = pb;
7809 }
7810
7811 /* Destroy and unlink this curpeers section.
7812 * Note: curpeers is backed up into *last.
7813 */
7814 free(curpeers->id);
7815 curpeers = curpeers->next;
7816 free(*last);
7817 *last = curpeers;
7818 }
7819 }
7820
Willy Tarreau34eb6712011-10-24 18:15:04 +02007821 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007822 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007823 MEM_F_SHARED);
7824
Willy Tarreaubb925012009-07-23 13:36:36 +02007825 if (cfgerr > 0)
7826 err_code |= ERR_ALERT | ERR_FATAL;
7827 out:
7828 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007829}
7830
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007831/*
7832 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7833 * parsing sessions.
7834 */
7835void cfg_register_keywords(struct cfg_kw_list *kwl)
7836{
7837 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7838}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007839
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007840/*
7841 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7842 */
7843void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7844{
7845 LIST_DEL(&kwl->list);
7846 LIST_INIT(&kwl->list);
7847}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007848
7849/*
7850 * Local variables:
7851 * c-indent-level: 8
7852 * c-basic-offset: 8
7853 * End:
7854 */