blob: ceaa96e4a9c77772abdd45dfe251fa9f54b25029 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100133 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100206 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100207 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
209 str = next;
210 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100211 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 *next++ = 0;
213 }
214
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100215 ss2 = str2sa_range(str, &port, &end, err,
216 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
217 if (!ss2)
218 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100220 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100221 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100226 if (!port || !end) {
227 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
228 goto fail;
229 }
230
Emeric Bruned760922010-10-22 17:59:25 +0200231 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200232 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200233 goto fail;
234 }
235
236 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200237 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200238 goto fail;
239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100241 else if (ss2->ss_family == AF_UNSPEC) {
242 socklen_t addr_len;
243
244 /* We want to attach to an already bound fd whose number
245 * is in the addr part of ss2 when cast to sockaddr_in.
246 * Note that by definition there is a single listener.
247 * We still have to determine the address family to
248 * register the correct protocol.
249 */
250 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
251 addr_len = sizeof(*ss2);
252 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
253 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
254 goto fail;
255 }
256
257 port = end = get_host_port(ss2);
258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100260 /* OK the address looks correct */
261 ss = *ss2;
262
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 for (; port <= end; port++) {
264 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100265 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau40aa0702013-03-10 23:51:38 +0100271 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200273 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100414/* Report it if a request ACL condition uses some keywords that are incompatible
415 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
416 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
417 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100419static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100420{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100421 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200422 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100425 return 0;
426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 acl = acl_cond_conflicts(cond, where);
428 if (acl) {
429 if (acl->name && *acl->name)
430 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
431 file, line, acl->name, sample_ckp_names(where));
432 else
433 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200434 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100435 return ERR_WARN;
436 }
437 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100438 return 0;
439
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100440 if (acl->name && *acl->name)
441 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200442 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 else
444 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100446 return ERR_WARN;
447}
448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200468 else if (!strcmp(args[0], "ca-base")) {
469#ifdef USE_OPENSSL
470 if (global.ca_base != NULL) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT;
473 goto out;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
479 }
480 global.ca_base = strdup(args[1]);
481#else
482 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
485#endif
486 }
487 else if (!strcmp(args[0], "crt-base")) {
488#ifdef USE_OPENSSL
489 if (global.crt_base != NULL) {
490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
491 err_code |= ERR_ALERT;
492 goto out;
493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
498 }
499 global.crt_base = strdup(args[1]);
500#else
501 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504#endif
505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200506 else if (!strcmp(args[0], "daemon")) {
507 global.mode |= MODE_DAEMON;
508 }
509 else if (!strcmp(args[0], "debug")) {
510 global.mode |= MODE_DEBUG;
511 }
512 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100513 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200515 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100521 else if (!strcmp(args[0], "nosplice")) {
522 global.tune.options &= ~GTUNE_USE_SPLICE;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 else if (!strcmp(args[0], "quiet")) {
525 global.mode |= MODE_QUIET;
526 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200527 else if (!strcmp(args[0], "tune.maxpollevents")) {
528 if (global.tune.maxpollevents != 0) {
529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 err_code |= ERR_ALERT;
531 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 }
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 global.tune.maxpollevents = atol(args[1]);
539 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100540 else if (!strcmp(args[0], "tune.maxaccept")) {
541 if (global.tune.maxaccept != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 err_code |= ERR_ALERT;
544 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 global.tune.maxaccept = atol(args[1]);
552 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200553 else if (!strcmp(args[0], "tune.chksize")) {
554 if (*(args[1]) == 0) {
555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT | ERR_FATAL;
557 goto out;
558 }
559 global.tune.chksize = atol(args[1]);
560 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200561#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100562 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.sslcachesize = atol(args[1]);
569 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100570 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
571 unsigned int ssllifetime;
572 const char *res;
573
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579
580 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
581 if (res) {
582 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
583 file, linenum, *res, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587
588 global.tune.ssllifetime = ssllifetime;
589 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100590 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.tune.ssl_max_record = atol(args[1]);
597 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200599 else if (!strcmp(args[0], "tune.bufsize")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.bufsize = atol(args[1]);
606 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
607 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100608 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100609 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200610 }
611 else if (!strcmp(args[0], "tune.maxrewrite")) {
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617 global.tune.maxrewrite = atol(args[1]);
618 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
619 global.tune.maxrewrite = global.tune.bufsize / 2;
620 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100621 else if (!strcmp(args[0], "tune.idletimer")) {
622 unsigned int idle;
623 const char *res;
624
625 if (*(args[1]) == 0) {
626 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT | ERR_FATAL;
628 goto out;
629 }
630
631 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
632 if (res) {
633 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
634 file, linenum, *res, args[0]);
635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
637 }
638
639 if (idle > 65535) {
640 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.idle_timer = idle;
645 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100646 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
647 if (global.tune.client_rcvbuf != 0) {
648 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT;
650 goto out;
651 }
652 if (*(args[1]) == 0) {
653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656 }
657 global.tune.client_rcvbuf = atol(args[1]);
658 }
659 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
660 if (global.tune.server_rcvbuf != 0) {
661 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT;
663 goto out;
664 }
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
669 }
670 global.tune.server_rcvbuf = atol(args[1]);
671 }
672 else if (!strcmp(args[0], "tune.sndbuf.client")) {
673 if (global.tune.client_sndbuf != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT;
676 goto out;
677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.client_sndbuf = atol(args[1]);
684 }
685 else if (!strcmp(args[0], "tune.sndbuf.server")) {
686 if (global.tune.server_sndbuf != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT;
689 goto out;
690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 global.tune.server_sndbuf = atol(args[1]);
697 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200698 else if (!strcmp(args[0], "tune.pipesize")) {
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.pipesize = atol(args[1]);
705 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100706 else if (!strcmp(args[0], "tune.http.cookielen")) {
707 if (*(args[1]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712 global.tune.cookie_len = atol(args[1]) + 1;
713 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200714 else if (!strcmp(args[0], "tune.http.maxhdr")) {
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.max_http_hdr = atol(args[1]);
721 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100722 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
723#ifdef USE_ZLIB
724 if (*args[1]) {
725 global.tune.zlibmemlevel = atoi(args[1]);
726 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
727 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
728 file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 } else {
733 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
734 file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#else
739 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742#endif
743 }
744 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
745#ifdef USE_ZLIB
746 if (*args[1]) {
747 global.tune.zlibwindowsize = atoi(args[1]);
748 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
749 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
750 file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 } else {
755 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760#else
761 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764#endif
765 }
William Lallemandf3747832012-11-09 12:33:10 +0100766 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
767 if (*args[1]) {
768 global.tune.comp_maxlevel = atoi(args[1]);
769 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
770 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
771 file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 } else {
776 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
777 file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 else if (!strcmp(args[0], "uid")) {
783 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200784 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT;
786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 }
788 if (*(args[1]) == 0) {
789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 }
793 global.uid = atol(args[1]);
794 }
795 else if (!strcmp(args[0], "gid")) {
796 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200797 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200798 err_code |= ERR_ALERT;
799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 }
801 if (*(args[1]) == 0) {
802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 }
806 global.gid = atol(args[1]);
807 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200808 /* user/group name handling */
809 else if (!strcmp(args[0], "user")) {
810 struct passwd *ha_user;
811 if (global.uid != 0) {
812 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
814 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200815 }
816 errno = 0;
817 ha_user = getpwnam(args[1]);
818 if (ha_user != NULL) {
819 global.uid = (int)ha_user->pw_uid;
820 }
821 else {
822 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200823 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200824 }
825 }
826 else if (!strcmp(args[0], "group")) {
827 struct group *ha_group;
828 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200829 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
831 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200832 }
833 errno = 0;
834 ha_group = getgrnam(args[1]);
835 if (ha_group != NULL) {
836 global.gid = (int)ha_group->gr_gid;
837 }
838 else {
839 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200840 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200841 }
842 }
843 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.nbproc = atol(args[1]);
851 }
852 else if (!strcmp(args[0], "maxconn")) {
853 if (global.maxconn != 0) {
854 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200855 err_code |= ERR_ALERT;
856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 }
863 global.maxconn = atol(args[1]);
864#ifdef SYSTEM_MAXCONN
865 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
866 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
867 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 }
870#endif /* SYSTEM_MAXCONN */
871 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200872 else if (!strcmp(args[0], "maxsslconn")) {
873#ifdef USE_OPENSSL
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.maxsslconn = atol(args[1]);
880#else
Emeric Brun0914df82012-10-02 18:45:42 +0200881 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200884#endif
885 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100886 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
887#ifdef USE_OPENSSL
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 free(global.listen_default_ciphers);
894 global.listen_default_ciphers = strdup(args[1]);
895#else
896 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899#endif
900 }
901 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
902#ifdef USE_OPENSSL
903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908 free(global.connect_default_ciphers);
909 global.connect_default_ciphers = strdup(args[1]);
910#else
911 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914#endif
915 }
Emeric Brun850efd52014-01-29 12:24:34 +0100916 else if (!strcmp(args[0], "ssl-server-verify")) {
917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 if (strcmp(args[1],"none") == 0)
923 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
924 else if (strcmp(args[1],"required") == 0)
925 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
926 else {
927 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200932 else if (!strcmp(args[0], "maxconnrate")) {
933 if (global.cps_lim != 0) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT;
936 goto out;
937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.cps_lim = atol(args[1]);
944 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200945 else if (!strcmp(args[0], "maxsessrate")) {
946 if (global.sps_lim != 0) {
947 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT;
949 goto out;
950 }
951 if (*(args[1]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
956 global.sps_lim = atol(args[1]);
957 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200958 else if (!strcmp(args[0], "maxsslrate")) {
959 if (global.ssl_lim != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
961 err_code |= ERR_ALERT;
962 goto out;
963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.ssl_lim = atol(args[1]);
970 }
William Lallemandd85f9172012-11-09 17:05:39 +0100971 else if (!strcmp(args[0], "maxcomprate")) {
972 if (*(args[1]) == 0) {
973 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 global.comp_rate_lim = atoi(args[1]) * 1024;
978 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100979 else if (!strcmp(args[0], "maxpipes")) {
980 if (global.maxpipes != 0) {
981 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200982 err_code |= ERR_ALERT;
983 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100984 }
985 if (*(args[1]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100989 }
990 global.maxpipes = atol(args[1]);
991 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100992 else if (!strcmp(args[0], "maxzlibmem")) {
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
William Lallemande3a7d992012-11-20 11:25:20 +0100998 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100999 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001000 else if (!strcmp(args[0], "maxcompcpuusage")) {
1001 if (*(args[1]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001007 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001008 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012}
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 else if (!strcmp(args[0], "ulimit-n")) {
1015 if (global.rlimit_nofile != 0) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT;
1018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 }
1020 if (*(args[1]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
1025 global.rlimit_nofile = atol(args[1]);
1026 }
1027 else if (!strcmp(args[0], "chroot")) {
1028 if (global.chroot != NULL) {
1029 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001030 err_code |= ERR_ALERT;
1031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 }
1033 if (*(args[1]) == 0) {
1034 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 global.chroot = strdup(args[1]);
1039 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001040 else if (!strcmp(args[0], "description")) {
1041 int i, len=0;
1042 char *d;
1043
1044 if (!*args[1]) {
1045 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1046 file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 for(i=1; *args[i]; i++)
1052 len += strlen(args[i])+1;
1053
1054 if (global.desc)
1055 free(global.desc);
1056
1057 global.desc = d = (char *)calloc(1, len);
1058
1059 d += sprintf(d, "%s", args[1]);
1060 for(i=2; *args[i]; i++)
1061 d += sprintf(d, " %s", args[i]);
1062 }
1063 else if (!strcmp(args[0], "node")) {
1064 int i;
1065 char c;
1066
1067 for (i=0; args[1][i]; i++) {
1068 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001069 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1070 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001071 break;
1072 }
1073
1074 if (!i || args[1][i]) {
1075 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1076 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1077 file, linenum, args[0]);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081
1082 if (global.node)
1083 free(global.node);
1084
1085 global.node = strdup(args[1]);
1086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 else if (!strcmp(args[0], "pidfile")) {
1088 if (global.pidfile != NULL) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
1098 global.pidfile = strdup(args[1]);
1099 }
Emeric Bruned760922010-10-22 17:59:25 +02001100 else if (!strcmp(args[0], "unix-bind")) {
1101 int cur_arg = 1;
1102 while (*(args[cur_arg])) {
1103 if (!strcmp(args[cur_arg], "prefix")) {
1104 if (global.unix_bind.prefix != NULL) {
1105 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1106 err_code |= ERR_ALERT;
1107 cur_arg += 2;
1108 continue;
1109 }
1110
1111 if (*(args[cur_arg+1]) == 0) {
1112 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1117 cur_arg += 2;
1118 continue;
1119 }
1120
1121 if (!strcmp(args[cur_arg], "mode")) {
1122
1123 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1124 cur_arg += 2;
1125 continue;
1126 }
1127
1128 if (!strcmp(args[cur_arg], "uid")) {
1129
1130 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1131 cur_arg += 2;
1132 continue;
1133 }
1134
1135 if (!strcmp(args[cur_arg], "gid")) {
1136
1137 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1138 cur_arg += 2;
1139 continue;
1140 }
1141
1142 if (!strcmp(args[cur_arg], "user")) {
1143 struct passwd *user;
1144
1145 user = getpwnam(args[cur_arg + 1]);
1146 if (!user) {
1147 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1148 file, linenum, args[0], args[cur_arg + 1 ]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152
1153 global.unix_bind.ux.uid = user->pw_uid;
1154 cur_arg += 2;
1155 continue;
1156 }
1157
1158 if (!strcmp(args[cur_arg], "group")) {
1159 struct group *group;
1160
1161 group = getgrnam(args[cur_arg + 1]);
1162 if (!group) {
1163 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1164 file, linenum, args[0], args[cur_arg + 1 ]);
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168
1169 global.unix_bind.ux.gid = group->gr_gid;
1170 cur_arg += 2;
1171 continue;
1172 }
1173
Willy Tarreaub48f9582011-09-05 01:17:06 +02001174 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001175 file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
1179 }
William Lallemand0f99e342011-10-12 17:50:54 +02001180 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1181 /* delete previous herited or defined syslog servers */
1182 struct logsrv *back;
1183 struct logsrv *tmp;
1184
1185 if (*(args[1]) != 0) {
1186 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190
1191 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1192 LIST_DEL(&tmp->list);
1193 free(tmp);
1194 }
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001197 struct sockaddr_storage *sk;
1198 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001199 struct logsrv *logsrv;
1200
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 if (*(args[1]) == 0 || *(args[2]) == 0) {
1202 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
William Lallemand0f99e342011-10-12 17:50:54 +02001206
1207 logsrv = calloc(1, sizeof(struct logsrv));
1208
1209 logsrv->facility = get_log_facility(args[2]);
1210 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001213 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
1215
William Lallemand0f99e342011-10-12 17:50:54 +02001216 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001218 logsrv->level = get_log_level(args[3]);
1219 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001221 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001222 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 }
1224 }
1225
William Lallemand0f99e342011-10-12 17:50:54 +02001226 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001227 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001228 logsrv->minlvl = get_log_level(args[4]);
1229 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001230 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001232 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001233 }
1234 }
1235
Willy Tarreau902636f2013-03-10 19:44:48 +01001236 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001237 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001238 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001239 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001240 free(logsrv);
1241 goto out;
1242 }
1243 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001244
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001245 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001246 if (port1 != port2) {
1247 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1248 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001249 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001250 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001251 goto out;
1252 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001253
William Lallemand0f99e342011-10-12 17:50:54 +02001254 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001255 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001256 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258
William Lallemand0f99e342011-10-12 17:50:54 +02001259 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001260 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001261 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1262 char *name;
1263 int len;
1264
1265 if (global.log_send_hostname != NULL) {
1266 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT;
1268 goto out;
1269 }
1270
1271 if (*(args[1]))
1272 name = args[1];
1273 else
1274 name = hostname;
1275
1276 len = strlen(name);
1277
1278 /* We'll add a space after the name to respect the log format */
1279 free(global.log_send_hostname);
1280 global.log_send_hostname = malloc(len + 2);
1281 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1282 }
Kevinm48936af2010-12-22 16:08:21 +00001283 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1284 if (*(args[1]) == 0) {
1285 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 free(global.log_tag);
1290 global.log_tag = strdup(args[1]);
1291 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001292 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1293 if (global.spread_checks != 0) {
1294 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001295 err_code |= ERR_ALERT;
1296 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001297 }
1298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001302 }
1303 global.spread_checks = atol(args[1]);
1304 if (global.spread_checks < 0 || global.spread_checks > 50) {
1305 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001306 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001309 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1310#ifdef USE_CPU_AFFINITY
1311 int cur_arg, i;
1312 unsigned int proc = 0;
1313 unsigned long cpus = 0;
1314
1315 if (strcmp(args[1], "all") == 0)
1316 proc = 0xFFFFFFFF;
1317 else if (strcmp(args[1], "odd") == 0)
1318 proc = 0x55555555;
1319 else if (strcmp(args[1], "even") == 0)
1320 proc = 0xAAAAAAAA;
1321 else {
1322 proc = atoi(args[1]);
1323 if (proc >= 1 && proc <= 32)
1324 proc = 1 << (proc - 1);
1325 }
1326
1327 if (!proc || !*args[2]) {
1328 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
1334 cur_arg = 2;
1335 while (*args[cur_arg]) {
1336 unsigned int low, high;
1337
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001338 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001339 char *dash = strchr(args[cur_arg], '-');
1340
1341 low = high = str2uic(args[cur_arg]);
1342 if (dash)
1343 high = str2uic(dash + 1);
1344
1345 if (high < low) {
1346 unsigned int swap = low;
1347 low = high;
1348 high = swap;
1349 }
1350
1351 if (low < 0 || high >= sizeof(long) * 8) {
1352 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1353 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357
1358 while (low <= high)
1359 cpus |= 1UL << low++;
1360 }
1361 else {
1362 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1363 file, linenum, args[0], args[cur_arg]);
1364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
1366 }
1367 cur_arg++;
1368 }
1369 for (i = 0; i < 32; i++)
1370 if (proc & (1 << i))
1371 global.cpu_map[i] = cpus;
1372#else
1373 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376#endif
1377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001379 struct cfg_kw_list *kwl;
1380 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001381 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001382
1383 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1384 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1385 if (kwl->kw[index].section != CFG_GLOBAL)
1386 continue;
1387 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001388 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001389 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001390 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001392 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001393 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001394 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001395 err_code |= ERR_WARN;
1396 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001397 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001399 }
1400 }
1401 }
1402
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001404 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406
Willy Tarreau058e9072009-07-20 09:30:05 +02001407 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001408 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410}
1411
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001412void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001414 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 defproxy.mode = PR_MODE_TCP;
1416 defproxy.state = PR_STNEW;
1417 defproxy.maxconn = cfg_maxpconn;
1418 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419
Simon Horman66183002013-02-23 10:16:43 +09001420 defproxy.defsrv.check.inter = DEF_CHKINTR;
1421 defproxy.defsrv.check.fastinter = 0;
1422 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001423 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1424 defproxy.defsrv.agent.fastinter = 0;
1425 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001426 defproxy.defsrv.check.rise = DEF_RISETIME;
1427 defproxy.defsrv.check.fall = DEF_FALLTIME;
1428 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1429 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001430 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001431 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001432 defproxy.defsrv.maxqueue = 0;
1433 defproxy.defsrv.minconn = 0;
1434 defproxy.defsrv.maxconn = 0;
1435 defproxy.defsrv.slowstart = 0;
1436 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1437 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1438 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439}
1440
Willy Tarreauade5ec42010-01-28 19:33:49 +01001441
1442static int create_cond_regex_rule(const char *file, int line,
1443 struct proxy *px, int dir, int action, int flags,
1444 const char *cmd, const char *reg, const char *repl,
1445 const char **cond_start)
1446{
1447 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001448 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001449 const char *err;
1450 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001451 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001452
1453 if (px == &defproxy) {
1454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1455 err_code |= ERR_ALERT | ERR_FATAL;
1456 goto err;
1457 }
1458
1459 if (*reg == 0) {
1460 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto err;
1463 }
1464
1465 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1466 err_code |= ERR_WARN;
1467
Willy Tarreau5321c422010-01-28 20:35:13 +01001468 if (cond_start &&
1469 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001470 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1471 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1472 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto err;
1475 }
1476 }
1477 else if (cond_start && **cond_start) {
1478 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1479 file, line, cmd, *cond_start);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto err;
1482 }
1483
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001484 err_code |= warnif_cond_conflicts(cond,
1485 (dir == SMP_OPT_DIR_REQ) ?
1486 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1487 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1488 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001489
Willy Tarreauade5ec42010-01-28 19:33:49 +01001490 preg = calloc(1, sizeof(regex_t));
1491 if (!preg) {
1492 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1493 err_code = ERR_ALERT | ERR_FATAL;
1494 goto err;
1495 }
1496
1497 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1498 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1499 err_code = ERR_ALERT | ERR_FATAL;
1500 goto err;
1501 }
1502
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001503 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001504 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001505 if (repl && err) {
1506 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1507 file, line, cmd, *err);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto err;
1510 }
1511
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001512 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001513 err_code |= ERR_WARN;
1514
Willy Tarreauf4068b62012-05-08 17:37:49 +02001515 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001516 return err_code;
1517 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001518 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001519 free(preg);
1520 return err_code;
1521}
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001525 * Returns the error code, 0 if OK, or any combination of :
1526 * - ERR_ABORT: must abort ASAP
1527 * - ERR_FATAL: we can continue parsing but not start the service
1528 * - ERR_WARN: a warning has been emitted
1529 * - ERR_ALERT: an alert has been emitted
1530 * Only the two first ones can stop processing, the two others are just
1531 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001533int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1534{
1535 static struct peers *curpeers = NULL;
1536 struct peer *newpeer = NULL;
1537 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001538 struct bind_conf *bind_conf;
1539 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001540 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001541 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001542
1543 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001544 if (!*args[1]) {
1545 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001546 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001547 goto out;
1548 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 err = invalid_char(args[1]);
1551 if (err) {
1552 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1553 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001554 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001555 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001556 }
1557
1558 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1559 /*
1560 * If there are two proxies with the same name only following
1561 * combinations are allowed:
1562 */
1563 if (strcmp(curpeers->id, args[1]) == 0) {
1564 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1565 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1566 err_code |= ERR_WARN;
1567 }
1568 }
1569
1570 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1571 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1572 err_code |= ERR_ALERT | ERR_ABORT;
1573 goto out;
1574 }
1575
1576 curpeers->next = peers;
1577 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001578 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001579 curpeers->conf.line = linenum;
1580 curpeers->last_change = now.tv_sec;
1581 curpeers->id = strdup(args[1]);
1582 }
1583 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001584 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001585 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001586 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001587
1588 if (!*args[2]) {
1589 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1590 file, linenum, args[0]);
1591 err_code |= ERR_ALERT | ERR_FATAL;
1592 goto out;
1593 }
1594
1595 err = invalid_char(args[1]);
1596 if (err) {
1597 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1598 file, linenum, *err, args[1]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
1601 }
1602
1603 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1604 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1605 err_code |= ERR_ALERT | ERR_ABORT;
1606 goto out;
1607 }
1608
1609 /* the peers are linked backwards first */
1610 curpeers->count++;
1611 newpeer->next = curpeers->remote;
1612 curpeers->remote = newpeer;
1613 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001614 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001615 newpeer->conf.line = linenum;
1616
1617 newpeer->last_change = now.tv_sec;
1618 newpeer->id = strdup(args[1]);
1619
Willy Tarreau902636f2013-03-10 19:44:48 +01001620 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001621 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001622 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001625 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001626
1627 proto = protocol_by_family(sk->ss_family);
1628 if (!proto || !proto->connect) {
1629 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1630 file, linenum, args[0], args[1]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001634
1635 if (port1 != port2) {
1636 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1637 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
1640 }
1641
Willy Tarreau2aa38802013-02-20 19:20:59 +01001642 if (!port1) {
1643 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1644 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
1647 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001648
Emeric Brun32da3c42010-09-23 18:39:19 +02001649 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001650 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001651 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001652 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001653
Emeric Brun32da3c42010-09-23 18:39:19 +02001654 if (strcmp(newpeer->id, localpeer) == 0) {
1655 /* Current is local peer, it define a frontend */
1656 newpeer->local = 1;
1657
1658 if (!curpeers->peers_fe) {
1659 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1660 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1661 err_code |= ERR_ALERT | ERR_ABORT;
1662 goto out;
1663 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001664
Willy Tarreau237250c2011-07-29 01:49:03 +02001665 init_new_proxy(curpeers->peers_fe);
1666 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001667
1668 curpeers->peers_fe->last_change = now.tv_sec;
1669 curpeers->peers_fe->id = strdup(args[1]);
1670 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001671 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001672 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1673 curpeers->peers_fe->timeout.connect = 5000;
1674 curpeers->peers_fe->accept = peer_accept;
1675 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001676 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1677 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001678
1679 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1680
Willy Tarreau902636f2013-03-10 19:44:48 +01001681 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1682 if (errmsg && *errmsg) {
1683 indent_msg(&errmsg, 2);
1684 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001685 }
1686 else
1687 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1688 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001689 err_code |= ERR_FATAL;
1690 goto out;
1691 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001692
1693 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1694 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1695 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1696 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1697 l->accept = session_accept;
1698 l->handler = process_session;
1699 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1700 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1701 global.maxsock += l->maxconn;
1702 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001703 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001704 else {
1705 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1706 file, linenum, args[0], args[1],
1707 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1708 err_code |= ERR_FATAL;
1709 goto out;
1710 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 }
1712 } /* neither "peer" nor "peers" */
1713 else if (*args[0] != 0) {
1714 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
1717 }
1718
1719out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001720 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 return err_code;
1722}
1723
Simon Horman69d29f92013-02-23 15:14:19 +09001724static int init_check(struct check *check, int type, const char * file, int linenum)
1725{
1726 check->type = type;
1727
1728 /* Allocate buffer for requests... */
1729 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1730 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1731 return ERR_ALERT | ERR_ABORT;
1732 }
1733 check->bi->size = global.tune.chksize;
1734
1735 /* Allocate buffer for responses... */
1736 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1737 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1738 return ERR_ALERT | ERR_ABORT;
1739 }
1740 check->bo->size = global.tune.chksize;
1741
1742 /* Allocate buffer for partial results... */
1743 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1744 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1745 return ERR_ALERT | ERR_ABORT;
1746 }
1747
1748 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1749
1750 return 0;
1751}
Emeric Brun32da3c42010-09-23 18:39:19 +02001752
Willy Tarreau3842f002009-06-14 11:39:52 +02001753int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754{
1755 static struct proxy *curproxy = NULL;
1756 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001757 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001758 int rc;
1759 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001760 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001761 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001762 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001763 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001764 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765
Willy Tarreau977b8e42006-12-29 14:19:17 +01001766 if (!strcmp(args[0], "listen"))
1767 rc = PR_CAP_LISTEN;
1768 else if (!strcmp(args[0], "frontend"))
1769 rc = PR_CAP_FE | PR_CAP_RS;
1770 else if (!strcmp(args[0], "backend"))
1771 rc = PR_CAP_BE | PR_CAP_RS;
1772 else if (!strcmp(args[0], "ruleset"))
1773 rc = PR_CAP_RS;
1774 else
1775 rc = PR_CAP_NONE;
1776
1777 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 if (!*args[1]) {
1779 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1780 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001782 err_code |= ERR_ALERT | ERR_ABORT;
1783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001785
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001786 err = invalid_char(args[1]);
1787 if (err) {
1788 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1789 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001791 }
1792
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001793 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1794 /*
1795 * If there are two proxies with the same name only following
1796 * combinations are allowed:
1797 *
1798 * listen backend frontend ruleset
1799 * listen - - - -
1800 * backend - - OK -
1801 * frontend - OK - -
1802 * ruleset - - - -
1803 */
1804
1805 if (!strcmp(curproxy->id, args[1]) &&
1806 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1807 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001808 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1809 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1810 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001812 }
1813 }
1814
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1816 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_ALERT | ERR_ABORT;
1818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001820
Willy Tarreau97cb7802010-01-03 20:23:58 +01001821 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 curproxy->next = proxy;
1823 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001824 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1825 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001826 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001828 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001829 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001830
1831 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001832 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001833 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001834
Willy Tarreau4348fad2012-09-20 16:48:07 +02001835 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1836
Willy Tarreau902636f2013-03-10 19:44:48 +01001837 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1838 if (errmsg && *errmsg) {
1839 indent_msg(&errmsg, 2);
1840 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001841 }
1842 else
1843 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1844 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001845 err_code |= ERR_FATAL;
1846 goto out;
1847 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001848
Willy Tarreau4348fad2012-09-20 16:48:07 +02001849 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001850 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001852 }
1853
1854 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001855 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001856 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001857
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001859 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001860 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001861 curproxy->no_options = defproxy.no_options;
1862 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001863 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001864 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001865 curproxy->except_net = defproxy.except_net;
1866 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001867 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001868 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001869
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001870 if (defproxy.fwdfor_hdr_len) {
1871 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1872 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1873 }
1874
Willy Tarreaub86db342009-11-30 11:50:16 +01001875 if (defproxy.orgto_hdr_len) {
1876 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1877 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1878 }
1879
Mark Lamourinec2247f02012-01-04 13:02:01 -05001880 if (defproxy.server_id_hdr_len) {
1881 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1882 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1883 }
1884
Willy Tarreau977b8e42006-12-29 14:19:17 +01001885 if (curproxy->cap & PR_CAP_FE) {
1886 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001887 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001888 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001889
1890 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001891 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1892 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001893
1894 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001896
Willy Tarreau977b8e42006-12-29 14:19:17 +01001897 if (curproxy->cap & PR_CAP_BE) {
1898 curproxy->fullconn = defproxy.fullconn;
1899 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001900
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001901 if (defproxy.check_req) {
1902 curproxy->check_req = calloc(1, defproxy.check_len);
1903 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1904 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001905 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001907 if (defproxy.expect_str) {
1908 curproxy->expect_str = strdup(defproxy.expect_str);
1909 if (defproxy.expect_regex) {
1910 /* note: this regex is known to be valid */
1911 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1912 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1913 }
1914 }
1915
Willy Tarreau67402132012-05-31 20:40:20 +02001916 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001917 if (defproxy.cookie_name)
1918 curproxy->cookie_name = strdup(defproxy.cookie_name);
1919 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001920 if (defproxy.cookie_domain)
1921 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001922
Willy Tarreau31936852010-10-06 16:59:56 +02001923 if (defproxy.cookie_maxidle)
1924 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1925
1926 if (defproxy.cookie_maxlife)
1927 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1928
Emeric Brun647caf12009-06-30 17:57:00 +02001929 if (defproxy.rdp_cookie_name)
1930 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1931 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1932
Willy Tarreau01732802007-11-01 22:48:15 +01001933 if (defproxy.url_param_name)
1934 curproxy->url_param_name = strdup(defproxy.url_param_name);
1935 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001936
Benoitaffb4812009-03-25 13:02:10 +01001937 if (defproxy.hh_name)
1938 curproxy->hh_name = strdup(defproxy.hh_name);
1939 curproxy->hh_len = defproxy.hh_len;
1940 curproxy->hh_match_domain = defproxy.hh_match_domain;
1941
Willy Tarreauef9a3602012-12-08 22:29:20 +01001942 if (defproxy.conn_src.iface_name)
1943 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1944 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001945 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001946#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001947 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001948#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001951 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001952 if (defproxy.capture_name)
1953 curproxy->capture_name = strdup(defproxy.capture_name);
1954 curproxy->capture_namelen = defproxy.capture_namelen;
1955 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001957
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001959 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001960 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001961 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001962 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001963 curproxy->uri_auth = defproxy.uri_auth;
1964 curproxy->mon_net = defproxy.mon_net;
1965 curproxy->mon_mask = defproxy.mon_mask;
1966 if (defproxy.monitor_uri)
1967 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1968 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001969 if (defproxy.defbe.name)
1970 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001971
1972 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001973 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1974 if (curproxy->conf.logformat_string &&
1975 curproxy->conf.logformat_string != default_http_log_format &&
1976 curproxy->conf.logformat_string != default_tcp_log_format &&
1977 curproxy->conf.logformat_string != clf_http_log_format)
1978 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1979
1980 if (defproxy.conf.lfs_file) {
1981 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1982 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1983 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001984 }
1985
1986 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001987 curproxy->timeout.connect = defproxy.timeout.connect;
1988 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001989 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001990 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001991 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001992 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001993 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001994 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001995 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001996 }
1997
Willy Tarreaubaaee002006-06-26 02:48:02 +02001998 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001999
2000 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002001 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002002 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002003 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002004 LIST_INIT(&node->list);
2005 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2006 }
2007
Willy Tarreau62a61232013-04-12 18:13:46 +02002008 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2009 if (curproxy->conf.uniqueid_format_string)
2010 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2011
2012 if (defproxy.conf.uif_file) {
2013 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2014 curproxy->conf.uif_line = defproxy.conf.uif_line;
2015 }
William Lallemanda73203e2012-03-12 12:48:57 +01002016
2017 /* copy default header unique id */
2018 if (defproxy.header_unique_id)
2019 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2020
William Lallemand82fe75c2012-10-23 10:25:10 +02002021 /* default compression options */
2022 if (defproxy.comp != NULL) {
2023 curproxy->comp = calloc(1, sizeof(struct comp));
2024 curproxy->comp->algos = defproxy.comp->algos;
2025 curproxy->comp->types = defproxy.comp->types;
2026 }
2027
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002029 curproxy->conf.used_listener_id = EB_ROOT;
2030 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002031
Willy Tarreau93893792009-07-23 13:19:11 +02002032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 }
2034 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2035 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002036 /* FIXME-20070101: we should do this too at the end of the
2037 * config parsing to free all default values.
2038 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002039 free(defproxy.check_req);
2040 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002041 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002042 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002043 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002044 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002045 free(defproxy.capture_name);
2046 free(defproxy.monitor_uri);
2047 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002048 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002049 free(defproxy.fwdfor_hdr_name);
2050 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002051 free(defproxy.orgto_hdr_name);
2052 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002053 free(defproxy.server_id_hdr_name);
2054 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002055 free(defproxy.expect_str);
2056 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002057
Willy Tarreau62a61232013-04-12 18:13:46 +02002058 if (defproxy.conf.logformat_string != default_http_log_format &&
2059 defproxy.conf.logformat_string != default_tcp_log_format &&
2060 defproxy.conf.logformat_string != clf_http_log_format)
2061 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002062
Willy Tarreau62a61232013-04-12 18:13:46 +02002063 free(defproxy.conf.uniqueid_format_string);
2064 free(defproxy.conf.lfs_file);
2065 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002066
Willy Tarreaua534fea2008-08-03 12:19:50 +02002067 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002068 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002069
Willy Tarreaubaaee002006-06-26 02:48:02 +02002070 /* we cannot free uri_auth because it might already be used */
2071 init_default_instance();
2072 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002073 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2074 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002075 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077 }
2078 else if (curproxy == NULL) {
2079 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002080 err_code |= ERR_ALERT | ERR_FATAL;
2081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002083
2084 /* update the current file and line being parsed */
2085 curproxy->conf.args.file = curproxy->conf.file;
2086 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002087
2088 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002090 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002091 int cur_arg;
2092
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 if (curproxy == &defproxy) {
2094 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002098 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002099 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100
Willy Tarreau24709282013-03-10 21:32:12 +01002101 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002102 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
2105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002107
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002108 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002109
2110 /* use default settings for unix sockets */
2111 bind_conf->ux.uid = global.unix_bind.ux.uid;
2112 bind_conf->ux.gid = global.unix_bind.ux.gid;
2113 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002114
2115 /* NOTE: the following line might create several listeners if there
2116 * are comma-separated IPs or port ranges. So all further processing
2117 * will have to be applied to all listeners created after last_listen.
2118 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002119 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2120 if (errmsg && *errmsg) {
2121 indent_msg(&errmsg, 2);
2122 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002123 }
2124 else
2125 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2126 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002127 err_code |= ERR_ALERT | ERR_FATAL;
2128 goto out;
2129 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002130
Willy Tarreau4348fad2012-09-20 16:48:07 +02002131 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2132 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002133 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002134 }
2135
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002136 cur_arg = 2;
2137 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002138 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002139 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002140 char *err;
2141
Willy Tarreau26982662012-09-12 23:17:10 +02002142 kw = bind_find_kw(args[cur_arg]);
2143 if (kw) {
2144 char *err = NULL;
2145 int code;
2146
2147 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002148 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2149 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002150 cur_arg += 1 + kw->skip ;
2151 err_code |= ERR_ALERT | ERR_FATAL;
2152 goto out;
2153 }
2154
Willy Tarreau4348fad2012-09-20 16:48:07 +02002155 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002156 err_code |= code;
2157
2158 if (code) {
2159 if (err && *err) {
2160 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002161 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002162 }
2163 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002164 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2165 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002166 if (code & ERR_FATAL) {
2167 free(err);
2168 cur_arg += 1 + kw->skip;
2169 goto out;
2170 }
2171 }
2172 free(err);
2173 cur_arg += 1 + kw->skip;
2174 continue;
2175 }
2176
Willy Tarreau8638f482012-09-18 18:01:17 +02002177 err = NULL;
2178 if (!bind_dumped) {
2179 bind_dump_kws(&err);
2180 indent_msg(&err, 4);
2181 bind_dumped = 1;
2182 }
2183
2184 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2185 file, linenum, args[0], args[1], args[cur_arg],
2186 err ? " Registered keywords :" : "", err ? err : "");
2187 free(err);
2188
Willy Tarreau93893792009-07-23 13:19:11 +02002189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002191 }
Willy Tarreau93893792009-07-23 13:19:11 +02002192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002193 }
2194 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2195 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2196 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2197 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002198 err_code |= ERR_ALERT | ERR_FATAL;
2199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002200 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002201 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002202 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002203
Willy Tarreaubaaee002006-06-26 02:48:02 +02002204 /* flush useless bits */
2205 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002207 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002208 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002210 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002211
Willy Tarreau1c47f852006-07-09 08:22:27 +02002212 if (!*args[1]) {
2213 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002217 }
2218
Willy Tarreaua534fea2008-08-03 12:19:50 +02002219 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002220 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002221 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002222 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002223 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2224
Willy Tarreau93893792009-07-23 13:19:11 +02002225 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2228 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2229 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2230 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2231 else {
2232 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 }
2236 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002237 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002238 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002239
2240 if (curproxy == &defproxy) {
2241 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2242 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002243 err_code |= ERR_ALERT | ERR_FATAL;
2244 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002245 }
2246
2247 if (!*args[1]) {
2248 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2249 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002252 }
2253
2254 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002255 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002256
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002257 if (curproxy->uuid <= 0) {
2258 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002259 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002260 err_code |= ERR_ALERT | ERR_FATAL;
2261 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002262 }
2263
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002264 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2265 if (node) {
2266 struct proxy *target = container_of(node, struct proxy, conf.id);
2267 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2268 file, linenum, proxy_type_str(curproxy), curproxy->id,
2269 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
2272 }
2273 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002274 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002275 else if (!strcmp(args[0], "description")) {
2276 int i, len=0;
2277 char *d;
2278
Cyril Bonté99ed3272010-01-24 23:29:44 +01002279 if (curproxy == &defproxy) {
2280 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2281 file, linenum, args[0]);
2282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
2284 }
2285
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002286 if (!*args[1]) {
2287 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2288 file, linenum, args[0]);
2289 return -1;
2290 }
2291
2292 for(i=1; *args[i]; i++)
2293 len += strlen(args[i])+1;
2294
2295 d = (char *)calloc(1, len);
2296 curproxy->desc = d;
2297
2298 d += sprintf(d, "%s", args[1]);
2299 for(i=2; *args[i]; i++)
2300 d += sprintf(d, " %s", args[i]);
2301
2302 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002303 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2304 curproxy->state = PR_STSTOPPED;
2305 }
2306 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2307 curproxy->state = PR_STNEW;
2308 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002309 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2310 int cur_arg = 1;
2311 unsigned int set = 0;
2312
2313 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002314 unsigned int low, high;
2315
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002316 if (strcmp(args[cur_arg], "all") == 0) {
2317 set = 0;
2318 break;
2319 }
2320 else if (strcmp(args[cur_arg], "odd") == 0) {
2321 set |= 0x55555555;
2322 }
2323 else if (strcmp(args[cur_arg], "even") == 0) {
2324 set |= 0xAAAAAAAA;
2325 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002326 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002327 char *dash = strchr(args[cur_arg], '-');
2328
2329 low = high = str2uic(args[cur_arg]);
2330 if (dash)
2331 high = str2uic(dash + 1);
2332
2333 if (high < low) {
2334 unsigned int swap = low;
2335 low = high;
2336 high = swap;
2337 }
2338
2339 if (low < 1 || high > 32) {
2340 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002341 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002342 err_code |= ERR_ALERT | ERR_FATAL;
2343 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002344 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002345
2346 if (high > global.nbproc) {
2347 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2348 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002349 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002350 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002351 while (low <= high)
2352 set |= 1 << (low++ - 1);
2353 }
2354 else {
2355 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2356 file, linenum, args[0]);
2357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002359 }
2360 cur_arg++;
2361 }
2362 curproxy->bind_proc = set;
2363 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002364 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002365 if (curproxy == &defproxy) {
2366 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002367 err_code |= ERR_ALERT | ERR_FATAL;
2368 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002369 }
2370
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002371 err = invalid_char(args[1]);
2372 if (err) {
2373 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2374 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002376 }
2377
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002378 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002379 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2380 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
2382 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002383 }
2384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2386 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002387
Willy Tarreau977b8e42006-12-29 14:19:17 +01002388 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002389 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002390
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 if (*(args[1]) == 0) {
2392 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2393 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002397
Willy Tarreau67402132012-05-31 20:40:20 +02002398 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002399 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002400 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002401 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 curproxy->cookie_name = strdup(args[1]);
2403 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002404
Willy Tarreaubaaee002006-06-26 02:48:02 +02002405 cur_arg = 2;
2406 while (*(args[cur_arg])) {
2407 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002408 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409 }
2410 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002411 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 }
2413 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002414 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 }
2416 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002417 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 }
2419 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002420 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002422 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002423 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002426 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002428 else if (!strcmp(args[cur_arg], "httponly")) {
2429 curproxy->ck_opts |= PR_CK_HTTPONLY;
2430 }
2431 else if (!strcmp(args[cur_arg], "secure")) {
2432 curproxy->ck_opts |= PR_CK_SECURE;
2433 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002434 else if (!strcmp(args[cur_arg], "domain")) {
2435 if (!*args[cur_arg + 1]) {
2436 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2437 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002440 }
2441
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002442 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002443 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002444 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2445 " dots nor does not start with a dot."
2446 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002447 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002448 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002449 }
2450
2451 err = invalid_domainchar(args[cur_arg + 1]);
2452 if (err) {
2453 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2454 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002457 }
2458
Willy Tarreau68a897b2009-12-03 23:28:34 +01002459 if (!curproxy->cookie_domain) {
2460 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2461 } else {
2462 /* one domain was already specified, add another one by
2463 * building the string which will be returned along with
2464 * the cookie.
2465 */
2466 char *new_ptr;
2467 int new_len = strlen(curproxy->cookie_domain) +
2468 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2469 new_ptr = malloc(new_len);
2470 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2471 free(curproxy->cookie_domain);
2472 curproxy->cookie_domain = new_ptr;
2473 }
Willy Tarreau31936852010-10-06 16:59:56 +02002474 cur_arg++;
2475 }
2476 else if (!strcmp(args[cur_arg], "maxidle")) {
2477 unsigned int maxidle;
2478 const char *res;
2479
2480 if (!*args[cur_arg + 1]) {
2481 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2482 file, linenum, args[cur_arg]);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2488 if (res) {
2489 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2490 file, linenum, *res, args[cur_arg]);
2491 err_code |= ERR_ALERT | ERR_FATAL;
2492 goto out;
2493 }
2494 curproxy->cookie_maxidle = maxidle;
2495 cur_arg++;
2496 }
2497 else if (!strcmp(args[cur_arg], "maxlife")) {
2498 unsigned int maxlife;
2499 const char *res;
2500
2501 if (!*args[cur_arg + 1]) {
2502 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2503 file, linenum, args[cur_arg]);
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507
2508 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2509 if (res) {
2510 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2511 file, linenum, *res, args[cur_arg]);
2512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
2514 }
2515 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002516 cur_arg++;
2517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002518 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002519 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 +02002520 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002521 err_code |= ERR_ALERT | ERR_FATAL;
2522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524 cur_arg++;
2525 }
Willy Tarreau67402132012-05-31 20:40:20 +02002526 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2528 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002529 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530 }
2531
Willy Tarreau67402132012-05-31 20:40:20 +02002532 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002537
Willy Tarreau67402132012-05-31 20:40:20 +02002538 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002539 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2540 file, linenum);
2541 err_code |= ERR_ALERT | ERR_FATAL;
2542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002544 else if (!strcmp(args[0], "persist")) { /* persist */
2545 if (*(args[1]) == 0) {
2546 Alert("parsing [%s:%d] : missing persist method.\n",
2547 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002550 }
2551
2552 if (!strncmp(args[1], "rdp-cookie", 10)) {
2553 curproxy->options2 |= PR_O2_RDPC_PRST;
2554
Emeric Brunb982a3d2010-01-04 15:45:53 +01002555 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002556 const char *beg, *end;
2557
2558 beg = args[1] + 11;
2559 end = strchr(beg, ')');
2560
2561 if (!end || end == beg) {
2562 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2563 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002566 }
2567
2568 free(curproxy->rdp_cookie_name);
2569 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2570 curproxy->rdp_cookie_len = end-beg;
2571 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002572 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002573 free(curproxy->rdp_cookie_name);
2574 curproxy->rdp_cookie_name = strdup("msts");
2575 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2576 }
2577 else { /* syntax */
2578 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2579 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002580 err_code |= ERR_ALERT | ERR_FATAL;
2581 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002582 }
2583 }
2584 else {
2585 Alert("parsing [%s:%d] : unknown persist method.\n",
2586 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002589 }
2590 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002592 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002594 if (curproxy == &defproxy) {
2595 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
2598 }
2599
Willy Tarreau977b8e42006-12-29 14:19:17 +01002600 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002601 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002602
Willy Tarreaubaaee002006-06-26 02:48:02 +02002603 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002604 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608 }
2609 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002610 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 curproxy->appsession_name = strdup(args[1]);
2612 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2613 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002614 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2615 if (err) {
2616 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2617 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002618 err_code |= ERR_ALERT | ERR_FATAL;
2619 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002620 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002621 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002622
Willy Tarreau51041c72007-09-09 21:56:53 +02002623 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2624 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002625 err_code |= ERR_ALERT | ERR_ABORT;
2626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002628
2629 cur_arg = 6;
2630 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002631 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2632 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002633 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002634 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002635 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002636 } else if (!strcmp(args[cur_arg], "prefix")) {
2637 curproxy->options2 |= PR_O2_AS_PFX;
2638 } else if (!strcmp(args[cur_arg], "mode")) {
2639 if (!*args[cur_arg + 1]) {
2640 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2641 file, linenum, args[0], args[cur_arg]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
2646 cur_arg++;
2647 if (!strcmp(args[cur_arg], "query-string")) {
2648 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2649 curproxy->options2 |= PR_O2_AS_M_QS;
2650 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2651 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2652 curproxy->options2 |= PR_O2_AS_M_PP;
2653 } else {
2654 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
2657 }
2658 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002659 cur_arg++;
2660 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002661 } /* Url App Session */
2662 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002663 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002664 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002665
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002667 if (curproxy == &defproxy) {
2668 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2669 err_code |= ERR_ALERT | ERR_FATAL;
2670 goto out;
2671 }
2672
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 if (*(args[4]) == 0) {
2674 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2675 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002679 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002680 curproxy->capture_name = strdup(args[2]);
2681 curproxy->capture_namelen = strlen(curproxy->capture_name);
2682 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002683 curproxy->to_log |= LW_COOKIE;
2684 }
2685 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2686 struct cap_hdr *hdr;
2687
2688 if (curproxy == &defproxy) {
2689 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 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }
2693
2694 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2695 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2696 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 }
2700
2701 hdr = calloc(sizeof(struct cap_hdr), 1);
2702 hdr->next = curproxy->req_cap;
2703 hdr->name = strdup(args[3]);
2704 hdr->namelen = strlen(args[3]);
2705 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002706 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 hdr->index = curproxy->nb_req_cap++;
2708 curproxy->req_cap = hdr;
2709 curproxy->to_log |= LW_REQHDR;
2710 }
2711 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2712 struct cap_hdr *hdr;
2713
2714 if (curproxy == &defproxy) {
2715 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 +02002716 err_code |= ERR_ALERT | ERR_FATAL;
2717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718 }
2719
2720 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2721 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2722 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002723 err_code |= ERR_ALERT | ERR_FATAL;
2724 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 }
2726 hdr = calloc(sizeof(struct cap_hdr), 1);
2727 hdr->next = curproxy->rsp_cap;
2728 hdr->name = strdup(args[3]);
2729 hdr->namelen = strlen(args[3]);
2730 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002731 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 hdr->index = curproxy->nb_rsp_cap++;
2733 curproxy->rsp_cap = hdr;
2734 curproxy->to_log |= LW_RSPHDR;
2735 }
2736 else {
2737 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2738 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002739 err_code |= ERR_ALERT | ERR_FATAL;
2740 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741 }
2742 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002746
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 if (*(args[1]) == 0) {
2748 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2749 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_ALERT | ERR_FATAL;
2751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 }
2753 curproxy->conn_retries = atol(args[1]);
2754 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002755 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002756 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002757
2758 if (curproxy == &defproxy) {
2759 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2760 err_code |= ERR_ALERT | ERR_FATAL;
2761 goto out;
2762 }
2763
Willy Tarreau20b0de52012-12-24 15:45:22 +01002764 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2765 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2766 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2767 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002768 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002769 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2770 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 +01002771 file, linenum, args[0]);
2772 err_code |= ERR_WARN;
2773 }
2774
Willy Tarreauff011f22011-01-06 17:51:27 +01002775 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002776
Willy Tarreauff011f22011-01-06 17:51:27 +01002777 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002778 err_code |= ERR_ALERT | ERR_ABORT;
2779 goto out;
2780 }
2781
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002782 err_code |= warnif_cond_conflicts(rule->cond,
2783 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2784 file, linenum);
2785
Willy Tarreauff011f22011-01-06 17:51:27 +01002786 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002787 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002788 else if (!strcmp(args[0], "http-response")) { /* response access control */
2789 struct http_res_rule *rule;
2790
2791 if (curproxy == &defproxy) {
2792 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
2795 }
2796
2797 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2798 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2799 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2800 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2801 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2802 file, linenum, args[0]);
2803 err_code |= ERR_WARN;
2804 }
2805
2806 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2807
2808 if (!rule) {
2809 err_code |= ERR_ALERT | ERR_ABORT;
2810 goto out;
2811 }
2812
2813 err_code |= warnif_cond_conflicts(rule->cond,
2814 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2815 file, linenum);
2816
2817 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2818 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002819 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2820 /* set the header name and length into the proxy structure */
2821 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2822 err_code |= ERR_WARN;
2823
2824 if (!*args[1]) {
2825 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2826 file, linenum, args[0]);
2827 err_code |= ERR_ALERT | ERR_FATAL;
2828 goto out;
2829 }
2830
2831 /* set the desired header name */
2832 free(curproxy->server_id_hdr_name);
2833 curproxy->server_id_hdr_name = strdup(args[1]);
2834 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2835 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002836 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002837 if (curproxy == &defproxy) {
2838 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002841 }
2842
Willy Tarreauef6494c2010-01-28 17:12:36 +01002843 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002844 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002848 }
2849
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002850 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2851 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2852 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_ALERT | ERR_FATAL;
2854 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002855 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002856
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002857 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002858 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002859 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002860 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002861 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002862
Cyril Bonté99ed3272010-01-24 23:29:44 +01002863 if (curproxy == &defproxy) {
2864 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867 }
2868
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002869 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002870 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2871 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002874 }
2875
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002876 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002877 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002878 err_code |= warnif_cond_conflicts(rule->cond,
2879 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2880 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002881 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002882 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002883 struct switching_rule *rule;
2884
Willy Tarreaub099aca2008-10-12 17:26:37 +02002885 if (curproxy == &defproxy) {
2886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002889 }
2890
Willy Tarreau55ea7572007-06-17 19:56:27 +02002891 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002893
2894 if (*(args[1]) == 0) {
2895 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002898 }
2899
Willy Tarreauef6494c2010-01-28 17:12:36 +01002900 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002901 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2902 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002905 }
2906
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002907 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2908 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2909 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002912 }
2913
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002914 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002915
Willy Tarreau55ea7572007-06-17 19:56:27 +02002916 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2917 rule->cond = cond;
2918 rule->be.name = strdup(args[1]);
2919 LIST_INIT(&rule->list);
2920 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2921 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002922 else if (strcmp(args[0], "use-server") == 0) {
2923 struct server_rule *rule;
2924
2925 if (curproxy == &defproxy) {
2926 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930
2931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2932 err_code |= ERR_WARN;
2933
2934 if (*(args[1]) == 0) {
2935 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2936 err_code |= ERR_ALERT | ERR_FATAL;
2937 goto out;
2938 }
2939
2940 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2941 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2942 file, linenum, args[0]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002947 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2948 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2949 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002954 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002955
2956 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2957 rule->cond = cond;
2958 rule->srv.name = strdup(args[1]);
2959 LIST_INIT(&rule->list);
2960 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2961 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2962 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002963 else if ((!strcmp(args[0], "force-persist")) ||
2964 (!strcmp(args[0], "ignore-persist"))) {
2965 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002966
2967 if (curproxy == &defproxy) {
2968 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972
2973 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2974 err_code |= ERR_WARN;
2975
Willy Tarreauef6494c2010-01-28 17:12:36 +01002976 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002977 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2978 file, linenum, args[0]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002983 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2984 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2985 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002990 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2991 * where force-persist is applied.
2992 */
2993 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002994
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002995 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002996 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002997 if (!strcmp(args[0], "force-persist")) {
2998 rule->type = PERSIST_TYPE_FORCE;
2999 } else {
3000 rule->type = PERSIST_TYPE_IGNORE;
3001 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003002 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003003 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003004 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003005 else if (!strcmp(args[0], "stick-table")) {
3006 int myidx = 1;
3007
Emeric Brun32da3c42010-09-23 18:39:19 +02003008 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003009 curproxy->table.type = (unsigned int)-1;
3010 while (*args[myidx]) {
3011 const char *err;
3012
3013 if (strcmp(args[myidx], "size") == 0) {
3014 myidx++;
3015 if (!*(args[myidx])) {
3016 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3017 file, linenum, args[myidx-1]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3022 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3023 file, linenum, *err, args[myidx-1]);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003027 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003028 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003029 else if (strcmp(args[myidx], "peers") == 0) {
3030 myidx++;
Godbach50523162013-12-11 19:48:57 +08003031 if (!*(args[myidx])) {
3032 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3033 file, linenum, args[myidx-1]);
3034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
3036 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003037 curproxy->table.peers.name = strdup(args[myidx++]);
3038 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003039 else if (strcmp(args[myidx], "expire") == 0) {
3040 myidx++;
3041 if (!*(args[myidx])) {
3042 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3043 file, linenum, args[myidx-1]);
3044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
3046 }
3047 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3048 if (err) {
3049 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3050 file, linenum, *err, args[myidx-1]);
3051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
3053 }
3054 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003055 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003056 }
3057 else if (strcmp(args[myidx], "nopurge") == 0) {
3058 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003059 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003060 }
3061 else if (strcmp(args[myidx], "type") == 0) {
3062 myidx++;
3063 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3064 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3065 file, linenum, args[myidx]);
3066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
3068 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003069 /* myidx already points to next arg */
3070 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003071 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003072 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003073 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003074
3075 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003076 nw = args[myidx];
3077 while (*nw) {
3078 /* the "store" keyword supports a comma-separated list */
3079 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003080 sa = NULL; /* store arg */
3081 while (*nw && *nw != ',') {
3082 if (*nw == '(') {
3083 *nw = 0;
3084 sa = ++nw;
3085 while (*nw != ')') {
3086 if (!*nw) {
3087 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3088 file, linenum, args[0], cw);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092 nw++;
3093 }
3094 *nw = '\0';
3095 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003096 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003097 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003098 if (*nw)
3099 *nw++ = '\0';
3100 type = stktable_get_data_type(cw);
3101 if (type < 0) {
3102 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3103 file, linenum, args[0], cw);
3104 err_code |= ERR_ALERT | ERR_FATAL;
3105 goto out;
3106 }
Willy Tarreauac782882010-06-20 10:41:54 +02003107
3108 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3109 switch (err) {
3110 case PE_NONE: break;
3111 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003112 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3113 file, linenum, args[0], cw);
3114 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003115 break;
3116
3117 case PE_ARG_MISSING:
3118 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3119 file, linenum, args[0], cw);
3120 err_code |= ERR_ALERT | ERR_FATAL;
3121 goto out;
3122
3123 case PE_ARG_NOT_USED:
3124 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3125 file, linenum, args[0], cw);
3126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128
3129 default:
3130 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3131 file, linenum, args[0], cw);
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003134 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003135 }
3136 myidx++;
3137 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003138 else {
3139 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3140 file, linenum, args[myidx]);
3141 err_code |= ERR_ALERT | ERR_FATAL;
3142 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003143 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003144 }
3145
3146 if (!curproxy->table.size) {
3147 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3148 file, linenum);
3149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
3151 }
3152
3153 if (curproxy->table.type == (unsigned int)-1) {
3154 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3155 file, linenum);
3156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
3158 }
3159 }
3160 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003161 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003162 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003163 int myidx = 0;
3164 const char *name = NULL;
3165 int flags;
3166
3167 if (curproxy == &defproxy) {
3168 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
3171 }
3172
3173 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3174 err_code |= ERR_WARN;
3175 goto out;
3176 }
3177
3178 myidx++;
3179 if ((strcmp(args[myidx], "store") == 0) ||
3180 (strcmp(args[myidx], "store-request") == 0)) {
3181 myidx++;
3182 flags = STK_IS_STORE;
3183 }
3184 else if (strcmp(args[myidx], "store-response") == 0) {
3185 myidx++;
3186 flags = STK_IS_STORE | STK_ON_RSP;
3187 }
3188 else if (strcmp(args[myidx], "match") == 0) {
3189 myidx++;
3190 flags = STK_IS_MATCH;
3191 }
3192 else if (strcmp(args[myidx], "on") == 0) {
3193 myidx++;
3194 flags = STK_IS_MATCH | STK_IS_STORE;
3195 }
3196 else {
3197 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
3200 }
3201
3202 if (*(args[myidx]) == 0) {
3203 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
3207
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003208 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003209 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003210 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003211 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003212 err_code |= ERR_ALERT | ERR_FATAL;
3213 goto out;
3214 }
3215
3216 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003217 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3218 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3219 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003220 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003221 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003222 goto out;
3223 }
3224 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003225 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3226 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3227 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003228 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003229 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003230 goto out;
3231 }
3232 }
3233
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003234 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003235 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003236
Emeric Brunb982a3d2010-01-04 15:45:53 +01003237 if (strcmp(args[myidx], "table") == 0) {
3238 myidx++;
3239 name = args[myidx++];
3240 }
3241
Willy Tarreauef6494c2010-01-28 17:12:36 +01003242 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003243 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3244 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3245 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003246 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003247 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003248 goto out;
3249 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003250 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003251 else if (*(args[myidx])) {
3252 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3253 file, linenum, args[0], args[myidx]);
3254 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003255 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003256 goto out;
3257 }
Emeric Brun97679e72010-09-23 17:56:44 +02003258 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003259 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003260 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003261 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003262
Emeric Brunb982a3d2010-01-04 15:45:53 +01003263 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3264 rule->cond = cond;
3265 rule->expr = expr;
3266 rule->flags = flags;
3267 rule->table.name = name ? strdup(name) : NULL;
3268 LIST_INIT(&rule->list);
3269 if (flags & STK_ON_RSP)
3270 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3271 else
3272 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003274 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003275 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003277
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3279 curproxy->uri_auth = NULL; /* we must detach from the default config */
3280
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003281 if (!*args[1]) {
3282 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003283 } else if (!strcmp(args[1], "admin")) {
3284 struct stats_admin_rule *rule;
3285
3286 if (curproxy == &defproxy) {
3287 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
3290 }
3291
3292 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3293 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3294 err_code |= ERR_ALERT | ERR_ABORT;
3295 goto out;
3296 }
3297
3298 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3299 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3300 file, linenum, args[0], args[1]);
3301 err_code |= ERR_ALERT | ERR_FATAL;
3302 goto out;
3303 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003304 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3305 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3306 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
3310
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003311 err_code |= warnif_cond_conflicts(cond,
3312 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3313 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003314
3315 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3316 rule->cond = cond;
3317 LIST_INIT(&rule->list);
3318 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 } else if (!strcmp(args[1], "uri")) {
3320 if (*(args[2]) == 0) {
3321 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3325 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 }
3329 } else if (!strcmp(args[1], "realm")) {
3330 if (*(args[2]) == 0) {
3331 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3335 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003336 err_code |= ERR_ALERT | ERR_ABORT;
3337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003339 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003340 unsigned interval;
3341
3342 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3343 if (err) {
3344 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3345 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003348 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3349 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003350 err_code |= ERR_ALERT | ERR_ABORT;
3351 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003352 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003353 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003354 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003355
3356 if (curproxy == &defproxy) {
3357 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
3360 }
3361
3362 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3363 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3364 err_code |= ERR_ALERT | ERR_ABORT;
3365 goto out;
3366 }
3367
Willy Tarreauff011f22011-01-06 17:51:27 +01003368 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3369 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003370 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3371 file, linenum, args[0]);
3372 err_code |= ERR_WARN;
3373 }
3374
Willy Tarreauff011f22011-01-06 17:51:27 +01003375 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003376
Willy Tarreauff011f22011-01-06 17:51:27 +01003377 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003378 err_code |= ERR_ALERT | ERR_ABORT;
3379 goto out;
3380 }
3381
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003382 err_code |= warnif_cond_conflicts(rule->cond,
3383 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3384 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003385 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003386
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 } else if (!strcmp(args[1], "auth")) {
3388 if (*(args[2]) == 0) {
3389 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3393 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003394 err_code |= ERR_ALERT | ERR_ABORT;
3395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 }
3397 } else if (!strcmp(args[1], "scope")) {
3398 if (*(args[2]) == 0) {
3399 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3403 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003404 err_code |= ERR_ALERT | ERR_ABORT;
3405 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
3407 } else if (!strcmp(args[1], "enable")) {
3408 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3409 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003410 err_code |= ERR_ALERT | ERR_ABORT;
3411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003413 } else if (!strcmp(args[1], "hide-version")) {
3414 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3415 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_ALERT | ERR_ABORT;
3417 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003418 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003419 } else if (!strcmp(args[1], "show-legends")) {
3420 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3421 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3422 err_code |= ERR_ALERT | ERR_ABORT;
3423 goto out;
3424 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003425 } else if (!strcmp(args[1], "show-node")) {
3426
3427 if (*args[2]) {
3428 int i;
3429 char c;
3430
3431 for (i=0; args[2][i]; i++) {
3432 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003433 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3434 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003435 break;
3436 }
3437
3438 if (!i || args[2][i]) {
3439 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3440 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3441 file, linenum, args[0], args[1]);
3442 err_code |= ERR_ALERT | ERR_FATAL;
3443 goto out;
3444 }
3445 }
3446
3447 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3448 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3449 err_code |= ERR_ALERT | ERR_ABORT;
3450 goto out;
3451 }
3452 } else if (!strcmp(args[1], "show-desc")) {
3453 char *desc = NULL;
3454
3455 if (*args[2]) {
3456 int i, len=0;
3457 char *d;
3458
3459 for(i=2; *args[i]; i++)
3460 len += strlen(args[i])+1;
3461
3462 desc = d = (char *)calloc(1, len);
3463
3464 d += sprintf(d, "%s", args[2]);
3465 for(i=3; *args[i]; i++)
3466 d += sprintf(d, " %s", args[i]);
3467 }
3468
3469 if (!*args[2] && !global.desc)
3470 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3471 file, linenum, args[1]);
3472 else {
3473 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3474 free(desc);
3475 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3476 err_code |= ERR_ALERT | ERR_ABORT;
3477 goto out;
3478 }
3479 free(desc);
3480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003482stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003483 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 +01003484 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 }
3488 }
3489 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003490 int optnum;
3491
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003492 if (*(args[1]) == '\0') {
3493 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3494 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003497 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003498
3499 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3500 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003501 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3502 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3503 file, linenum, cfg_opts[optnum].name);
3504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
3506 }
Willy Tarreau93893792009-07-23 13:19:11 +02003507 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3508 err_code |= ERR_WARN;
3509 goto out;
3510 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003511
Willy Tarreau3842f002009-06-14 11:39:52 +02003512 curproxy->no_options &= ~cfg_opts[optnum].val;
3513 curproxy->options &= ~cfg_opts[optnum].val;
3514
3515 switch (kwm) {
3516 case KWM_STD:
3517 curproxy->options |= cfg_opts[optnum].val;
3518 break;
3519 case KWM_NO:
3520 curproxy->no_options |= cfg_opts[optnum].val;
3521 break;
3522 case KWM_DEF: /* already cleared */
3523 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003524 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003525
Willy Tarreau93893792009-07-23 13:19:11 +02003526 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003527 }
3528 }
3529
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003530 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3531 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003532 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3533 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3534 file, linenum, cfg_opts2[optnum].name);
3535 err_code |= ERR_ALERT | ERR_FATAL;
3536 goto out;
3537 }
Willy Tarreau93893792009-07-23 13:19:11 +02003538 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3539 err_code |= ERR_WARN;
3540 goto out;
3541 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003542
Willy Tarreau3842f002009-06-14 11:39:52 +02003543 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3544 curproxy->options2 &= ~cfg_opts2[optnum].val;
3545
3546 switch (kwm) {
3547 case KWM_STD:
3548 curproxy->options2 |= cfg_opts2[optnum].val;
3549 break;
3550 case KWM_NO:
3551 curproxy->no_options2 |= cfg_opts2[optnum].val;
3552 break;
3553 case KWM_DEF: /* already cleared */
3554 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003555 }
Willy Tarreau93893792009-07-23 13:19:11 +02003556 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003557 }
3558 }
3559
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003560 /* HTTP options override each other. They can be cancelled using
3561 * "no option xxx" which only switches to default mode if the mode
3562 * was this one (useful for cancelling options set in defaults
3563 * sections).
3564 */
3565 if (strcmp(args[1], "httpclose") == 0) {
3566 if (kwm == KWM_STD) {
3567 curproxy->options &= ~PR_O_HTTP_MODE;
3568 curproxy->options |= PR_O_HTTP_PCL;
3569 goto out;
3570 }
3571 else if (kwm == KWM_NO) {
3572 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3573 curproxy->options &= ~PR_O_HTTP_MODE;
3574 goto out;
3575 }
3576 }
3577 else if (strcmp(args[1], "forceclose") == 0) {
3578 if (kwm == KWM_STD) {
3579 curproxy->options &= ~PR_O_HTTP_MODE;
3580 curproxy->options |= PR_O_HTTP_FCL;
3581 goto out;
3582 }
3583 else if (kwm == KWM_NO) {
3584 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3585 curproxy->options &= ~PR_O_HTTP_MODE;
3586 goto out;
3587 }
3588 }
3589 else if (strcmp(args[1], "http-server-close") == 0) {
3590 if (kwm == KWM_STD) {
3591 curproxy->options &= ~PR_O_HTTP_MODE;
3592 curproxy->options |= PR_O_HTTP_SCL;
3593 goto out;
3594 }
3595 else if (kwm == KWM_NO) {
3596 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3597 curproxy->options &= ~PR_O_HTTP_MODE;
3598 goto out;
3599 }
3600 }
3601 else if (strcmp(args[1], "http-keep-alive") == 0) {
3602 if (kwm == KWM_STD) {
3603 curproxy->options &= ~PR_O_HTTP_MODE;
3604 curproxy->options |= PR_O_HTTP_KAL;
3605 goto out;
3606 }
3607 else if (kwm == KWM_NO) {
3608 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3609 curproxy->options &= ~PR_O_HTTP_MODE;
3610 goto out;
3611 }
3612 }
3613 else if (strcmp(args[1], "http-tunnel") == 0) {
3614 if (kwm == KWM_STD) {
3615 curproxy->options &= ~PR_O_HTTP_MODE;
3616 curproxy->options |= PR_O_HTTP_TUN;
3617 goto out;
3618 }
3619 else if (kwm == KWM_NO) {
3620 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3621 curproxy->options &= ~PR_O_HTTP_MODE;
3622 goto out;
3623 }
3624 }
3625
Willy Tarreau3842f002009-06-14 11:39:52 +02003626 if (kwm != KWM_STD) {
3627 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003628 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003631 }
3632
Emeric Brun3a058f32009-06-30 18:26:00 +02003633 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003634 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003636 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003637 if (*(args[2]) != '\0') {
3638 if (!strcmp(args[2], "clf")) {
3639 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003640 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003641 } else {
3642 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003645 }
3646 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003647 if (curproxy->conf.logformat_string != default_http_log_format &&
3648 curproxy->conf.logformat_string != default_tcp_log_format &&
3649 curproxy->conf.logformat_string != clf_http_log_format)
3650 free(curproxy->conf.logformat_string);
3651 curproxy->conf.logformat_string = logformat;
3652
3653 free(curproxy->conf.lfs_file);
3654 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3655 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003656 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003657 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003658 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003659 if (curproxy->conf.logformat_string != default_http_log_format &&
3660 curproxy->conf.logformat_string != default_tcp_log_format &&
3661 curproxy->conf.logformat_string != clf_http_log_format)
3662 free(curproxy->conf.logformat_string);
3663 curproxy->conf.logformat_string = default_tcp_log_format;
3664
3665 free(curproxy->conf.lfs_file);
3666 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3667 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003669 else if (!strcmp(args[1], "tcpka")) {
3670 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003671 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003672 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003673
3674 if (curproxy->cap & PR_CAP_FE)
3675 curproxy->options |= PR_O_TCP_CLI_KA;
3676 if (curproxy->cap & PR_CAP_BE)
3677 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 }
3679 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003680 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_WARN;
3682
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003684 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003685 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003686 curproxy->options2 &= ~PR_O2_CHK_ANY;
3687 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 if (!*args[2]) { /* no argument */
3689 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3690 curproxy->check_len = strlen(DEF_CHECK_REQ);
3691 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003692 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 curproxy->check_req = (char *)malloc(reqlen);
3694 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003695 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003697 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 if (*args[4])
3699 reqlen += strlen(args[4]);
3700 else
3701 reqlen += strlen("HTTP/1.0");
3702
3703 curproxy->check_req = (char *)malloc(reqlen);
3704 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003705 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003707 }
3708 else if (!strcmp(args[1], "ssl-hello-chk")) {
3709 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003711 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003712
Willy Tarreaua534fea2008-08-03 12:19:50 +02003713 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003714 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003715 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003716 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003717 }
Willy Tarreau23677902007-05-08 23:50:35 +02003718 else if (!strcmp(args[1], "smtpchk")) {
3719 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003720 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003721 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003722 curproxy->options2 &= ~PR_O2_CHK_ANY;
3723 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003724
3725 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3726 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3727 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3728 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3729 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3730 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3731 curproxy->check_req = (char *)malloc(reqlen);
3732 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3733 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3734 } else {
3735 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3736 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3737 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3738 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3739 }
3740 }
3741 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003742 else if (!strcmp(args[1], "pgsql-check")) {
3743 /* use PostgreSQL request to check servers' health */
3744 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3745 err_code |= ERR_WARN;
3746
3747 free(curproxy->check_req);
3748 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003749 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003750 curproxy->options2 |= PR_O2_PGSQL_CHK;
3751
3752 if (*(args[2])) {
3753 int cur_arg = 2;
3754
3755 while (*(args[cur_arg])) {
3756 if (strcmp(args[cur_arg], "user") == 0) {
3757 char * packet;
3758 uint32_t packet_len;
3759 uint32_t pv;
3760
3761 /* suboption header - needs additional argument for it */
3762 if (*(args[cur_arg+1]) == 0) {
3763 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3764 file, linenum, args[0], args[1], args[cur_arg]);
3765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
3767 }
3768
3769 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3770 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3771 pv = htonl(0x30000); /* protocol version 3.0 */
3772
3773 packet = (char*) calloc(1, packet_len);
3774
3775 memcpy(packet + 4, &pv, 4);
3776
3777 /* copy "user" */
3778 memcpy(packet + 8, "user", 4);
3779
3780 /* copy username */
3781 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3782
3783 free(curproxy->check_req);
3784 curproxy->check_req = packet;
3785 curproxy->check_len = packet_len;
3786
3787 packet_len = htonl(packet_len);
3788 memcpy(packet, &packet_len, 4);
3789 cur_arg += 2;
3790 } else {
3791 /* unknown suboption - catchall */
3792 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3793 file, linenum, args[0], args[1]);
3794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
3796 }
3797 } /* end while loop */
3798 }
3799 }
3800
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003801 else if (!strcmp(args[1], "redis-check")) {
3802 /* use REDIS PING request to check servers' health */
3803 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3804 err_code |= ERR_WARN;
3805
3806 free(curproxy->check_req);
3807 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003808 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003809 curproxy->options2 |= PR_O2_REDIS_CHK;
3810
3811 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3812 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3813 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3814 }
3815
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003816 else if (!strcmp(args[1], "mysql-check")) {
3817 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003818 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3819 err_code |= ERR_WARN;
3820
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003821 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003822 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003823 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003824 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003825
3826 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3827 * const char mysql40_client_auth_pkt[] = {
3828 * "\x0e\x00\x00" // packet length
3829 * "\x01" // packet number
3830 * "\x00\x00" // client capabilities
3831 * "\x00\x00\x01" // max packet
3832 * "haproxy\x00" // username (null terminated string)
3833 * "\x00" // filler (always 0x00)
3834 * "\x01\x00\x00" // packet length
3835 * "\x00" // packet number
3836 * "\x01" // COM_QUIT command
3837 * };
3838 */
3839
3840 if (*(args[2])) {
3841 int cur_arg = 2;
3842
3843 while (*(args[cur_arg])) {
3844 if (strcmp(args[cur_arg], "user") == 0) {
3845 char *mysqluser;
3846 int packetlen, reqlen, userlen;
3847
3848 /* suboption header - needs additional argument for it */
3849 if (*(args[cur_arg+1]) == 0) {
3850 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3851 file, linenum, args[0], args[1], args[cur_arg]);
3852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
3854 }
3855 mysqluser = args[cur_arg + 1];
3856 userlen = strlen(mysqluser);
3857 packetlen = userlen + 7;
3858 reqlen = packetlen + 9;
3859
3860 free(curproxy->check_req);
3861 curproxy->check_req = (char *)calloc(1, reqlen);
3862 curproxy->check_len = reqlen;
3863
3864 snprintf(curproxy->check_req, 4, "%c%c%c",
3865 ((unsigned char) packetlen & 0xff),
3866 ((unsigned char) (packetlen >> 8) & 0xff),
3867 ((unsigned char) (packetlen >> 16) & 0xff));
3868
3869 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003870 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003871 curproxy->check_req[8] = 1;
3872 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3873 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3874 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3875 cur_arg += 2;
3876 } else {
3877 /* unknown suboption - catchall */
3878 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3879 file, linenum, args[0], args[1]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 } /* end while loop */
3884 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003885 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003886 else if (!strcmp(args[1], "ldap-check")) {
3887 /* use LDAP request to check servers' health */
3888 free(curproxy->check_req);
3889 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003890 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003891 curproxy->options2 |= PR_O2_LDAP_CHK;
3892
3893 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3894 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3895 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3896 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003897 else if (!strcmp(args[1], "tcp-check")) {
3898 /* use raw TCPCHK send/expect to check servers' health */
3899 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3900 err_code |= ERR_WARN;
3901
3902 free(curproxy->check_req);
3903 curproxy->check_req = NULL;
3904 curproxy->options2 &= ~PR_O2_CHK_ANY;
3905 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3906 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003907 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003908 int cur_arg;
3909
3910 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3911 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003912 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003913
Willy Tarreau87cf5142011-08-19 22:57:24 +02003914 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003915
3916 free(curproxy->fwdfor_hdr_name);
3917 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3918 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3919
3920 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3921 cur_arg = 2;
3922 while (*(args[cur_arg])) {
3923 if (!strcmp(args[cur_arg], "except")) {
3924 /* suboption except - needs additional argument for it */
3925 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3926 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3927 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003930 }
3931 /* flush useless bits */
3932 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003933 cur_arg += 2;
3934 } else if (!strcmp(args[cur_arg], "header")) {
3935 /* suboption header - needs additional argument for it */
3936 if (*(args[cur_arg+1]) == 0) {
3937 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3938 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003941 }
3942 free(curproxy->fwdfor_hdr_name);
3943 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3944 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3945 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003946 } else if (!strcmp(args[cur_arg], "if-none")) {
3947 curproxy->options &= ~PR_O_FF_ALWAYS;
3948 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003949 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003950 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003951 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003952 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003953 err_code |= ERR_ALERT | ERR_FATAL;
3954 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003955 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003956 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003957 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003958 else if (!strcmp(args[1], "originalto")) {
3959 int cur_arg;
3960
3961 /* insert x-original-to field, but not for the IP address listed as an except.
3962 * set default options (ie: bitfield, header name, etc)
3963 */
3964
3965 curproxy->options |= PR_O_ORGTO;
3966
3967 free(curproxy->orgto_hdr_name);
3968 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3969 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3970
Willy Tarreau87cf5142011-08-19 22:57:24 +02003971 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003972 cur_arg = 2;
3973 while (*(args[cur_arg])) {
3974 if (!strcmp(args[cur_arg], "except")) {
3975 /* suboption except - needs additional argument for it */
3976 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3977 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3978 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003981 }
3982 /* flush useless bits */
3983 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3984 cur_arg += 2;
3985 } else if (!strcmp(args[cur_arg], "header")) {
3986 /* suboption header - needs additional argument for it */
3987 if (*(args[cur_arg+1]) == 0) {
3988 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3989 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003992 }
3993 free(curproxy->orgto_hdr_name);
3994 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3995 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3996 cur_arg += 2;
3997 } else {
3998 /* unknown suboption - catchall */
3999 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4000 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004001 err_code |= ERR_ALERT | ERR_FATAL;
4002 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004003 }
4004 } /* end while loop */
4005 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 else {
4007 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004010 }
Willy Tarreau93893792009-07-23 13:19:11 +02004011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004013 else if (!strcmp(args[0], "default_backend")) {
4014 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004015 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004016
4017 if (*(args[1]) == 0) {
4018 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004021 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004022 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004023 curproxy->defbe.name = strdup(args[1]);
4024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004025 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004026 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004027 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004028
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004029 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004031 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004032 /* enable reconnections to dispatch */
4033 curproxy->options |= PR_O_REDISP;
4034 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004035 else if (!strcmp(args[0], "http-check")) {
4036 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004038
4039 if (strcmp(args[1], "disable-on-404") == 0) {
4040 /* enable a graceful server shutdown on an HTTP 404 response */
4041 curproxy->options |= PR_O_DISABLE404;
4042 }
Willy Tarreauef781042010-01-27 11:53:01 +01004043 else if (strcmp(args[1], "send-state") == 0) {
4044 /* enable emission of the apparent state of a server in HTTP checks */
4045 curproxy->options2 |= PR_O2_CHK_SNDST;
4046 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004047 else if (strcmp(args[1], "expect") == 0) {
4048 const char *ptr_arg;
4049 int cur_arg;
4050
4051 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4052 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
4055 }
4056
4057 cur_arg = 2;
4058 /* consider exclamation marks, sole or at the beginning of a word */
4059 while (*(ptr_arg = args[cur_arg])) {
4060 while (*ptr_arg == '!') {
4061 curproxy->options2 ^= PR_O2_EXP_INV;
4062 ptr_arg++;
4063 }
4064 if (*ptr_arg)
4065 break;
4066 cur_arg++;
4067 }
4068 /* now ptr_arg points to the beginning of a word past any possible
4069 * exclamation mark, and cur_arg is the argument which holds this word.
4070 */
4071 if (strcmp(ptr_arg, "status") == 0) {
4072 if (!*(args[cur_arg + 1])) {
4073 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4074 file, linenum, args[0], args[1], ptr_arg);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
4078 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004079 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004080 curproxy->expect_str = strdup(args[cur_arg + 1]);
4081 }
4082 else if (strcmp(ptr_arg, "string") == 0) {
4083 if (!*(args[cur_arg + 1])) {
4084 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4085 file, linenum, args[0], args[1], ptr_arg);
4086 err_code |= ERR_ALERT | ERR_FATAL;
4087 goto out;
4088 }
4089 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004090 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004091 curproxy->expect_str = strdup(args[cur_arg + 1]);
4092 }
4093 else if (strcmp(ptr_arg, "rstatus") == 0) {
4094 if (!*(args[cur_arg + 1])) {
4095 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4096 file, linenum, args[0], args[1], ptr_arg);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
4100 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004101 free(curproxy->expect_str);
4102 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4103 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004104 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4105 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4106 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4107 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
4111 }
4112 else if (strcmp(ptr_arg, "rstring") == 0) {
4113 if (!*(args[cur_arg + 1])) {
4114 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4115 file, linenum, args[0], args[1], ptr_arg);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004120 free(curproxy->expect_str);
4121 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4122 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004123 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4124 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4125 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4126 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4127 err_code |= ERR_ALERT | ERR_FATAL;
4128 goto out;
4129 }
4130 }
4131 else {
4132 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4133 file, linenum, args[0], args[1], ptr_arg);
4134 err_code |= ERR_ALERT | ERR_FATAL;
4135 goto out;
4136 }
4137 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004138 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004139 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 +02004140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004142 }
4143 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004144 else if (!strcmp(args[0], "tcp-check")) {
4145 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4146 err_code |= ERR_WARN;
4147
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004148 if (strcmp(args[1], "connect") == 0) {
4149 const char *ptr_arg;
4150 int cur_arg;
4151 struct tcpcheck_rule *tcpcheck;
4152 struct list *l;
4153
4154 /* check if first rule is also a 'connect' action */
4155 l = (struct list *)&curproxy->tcpcheck_rules;
4156 if (l->p != l->n) {
4157 tcpcheck = (struct tcpcheck_rule *)l->n;
4158 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4159 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4160 file, linenum);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164 }
4165
4166 cur_arg = 2;
4167 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4168 tcpcheck->action = TCPCHK_ACT_CONNECT;
4169
4170 /* parsing each parameters to fill up the rule */
4171 while (*(ptr_arg = args[cur_arg])) {
4172 /* tcp port */
4173 if (strcmp(args[cur_arg], "port") == 0) {
4174 if ( (atol(args[cur_arg + 1]) > 65535) ||
4175 (atol(args[cur_arg + 1]) < 1) ){
4176 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4177 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181 tcpcheck->port = atol(args[cur_arg + 1]);
4182 cur_arg += 2;
4183 }
4184 /* send proxy protocol */
4185 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4186 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4187 cur_arg++;
4188 }
4189#ifdef USE_OPENSSL
4190 else if (strcmp(args[cur_arg], "ssl") == 0) {
4191 curproxy->options |= PR_O_TCPCHK_SSL;
4192 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4193 cur_arg++;
4194 }
4195#endif /* USE_OPENSSL */
4196 else {
4197#ifdef USE_OPENSSL
4198 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4199#else /* USE_OPENSSL */
4200 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4201#endif /* USE_OPENSSL */
4202 file, linenum, args[0], args[1], args[cur_arg]);
4203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
4205 }
4206
4207 }
4208
4209 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4210 }
4211 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004212 if (! *(args[2]) ) {
4213 /* SEND string expected */
4214 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4215 file, linenum, args[0], args[1], args[2]);
4216 err_code |= ERR_ALERT | ERR_FATAL;
4217 goto out;
4218 } else {
4219 struct tcpcheck_rule *tcpcheck;
4220
4221 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4222
4223 tcpcheck->action = TCPCHK_ACT_SEND;
4224 tcpcheck->string_len = strlen(args[2]);
4225 tcpcheck->string = strdup(args[2]);
4226 tcpcheck->expect_regex = NULL;
4227
4228 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4229 }
4230 }
4231 else if (strcmp(args[1], "send-binary") == 0) {
4232 if (! *(args[2]) ) {
4233 /* SEND binary string expected */
4234 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4235 file, linenum, args[0], args[1], args[2]);
4236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
4238 } else {
4239 struct tcpcheck_rule *tcpcheck;
4240 char *err = NULL;
4241
4242 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4243
4244 tcpcheck->action = TCPCHK_ACT_SEND;
4245 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4246 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4247 file, linenum, args[0], args[1], args[2], err);
4248 err_code |= ERR_ALERT | ERR_FATAL;
4249 goto out;
4250 }
4251 tcpcheck->expect_regex = NULL;
4252
4253 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4254 }
4255 }
4256 else if (strcmp(args[1], "expect") == 0) {
4257 const char *ptr_arg;
4258 int cur_arg;
4259 int inverse = 0;
4260
4261 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4262 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
4266
4267 cur_arg = 2;
4268 /* consider exclamation marks, sole or at the beginning of a word */
4269 while (*(ptr_arg = args[cur_arg])) {
4270 while (*ptr_arg == '!') {
4271 inverse = !inverse;
4272 ptr_arg++;
4273 }
4274 if (*ptr_arg)
4275 break;
4276 cur_arg++;
4277 }
4278 /* now ptr_arg points to the beginning of a word past any possible
4279 * exclamation mark, and cur_arg is the argument which holds this word.
4280 */
4281 if (strcmp(ptr_arg, "binary") == 0) {
4282 if (!*(args[cur_arg + 1])) {
4283 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4284 file, linenum, args[0], args[1], ptr_arg);
4285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287 }
4288 struct tcpcheck_rule *tcpcheck;
4289 char *err = NULL;
4290
4291 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4292
4293 tcpcheck->action = TCPCHK_ACT_EXPECT;
4294 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4295 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4296 file, linenum, args[0], args[1], args[2], err);
4297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
4300 tcpcheck->expect_regex = NULL;
4301 tcpcheck->inverse = inverse;
4302
4303 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4304 }
4305 else if (strcmp(ptr_arg, "string") == 0) {
4306 if (!*(args[cur_arg + 1])) {
4307 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4308 file, linenum, args[0], args[1], ptr_arg);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
4312 struct tcpcheck_rule *tcpcheck;
4313
4314 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4315
4316 tcpcheck->action = TCPCHK_ACT_EXPECT;
4317 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4318 tcpcheck->string = strdup(args[cur_arg + 1]);
4319 tcpcheck->expect_regex = NULL;
4320 tcpcheck->inverse = inverse;
4321
4322 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4323 }
4324 else if (strcmp(ptr_arg, "rstring") == 0) {
4325 if (!*(args[cur_arg + 1])) {
4326 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4327 file, linenum, args[0], args[1], ptr_arg);
4328 err_code |= ERR_ALERT | ERR_FATAL;
4329 goto out;
4330 }
4331 struct tcpcheck_rule *tcpcheck;
4332
4333 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4334
4335 tcpcheck->action = TCPCHK_ACT_EXPECT;
4336 tcpcheck->string_len = 0;
4337 tcpcheck->string = NULL;
4338 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4339 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4340 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4341 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345 tcpcheck->inverse = inverse;
4346
4347 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4348 }
4349 else {
4350 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4351 file, linenum, args[0], args[1], ptr_arg);
4352 err_code |= ERR_ALERT | ERR_FATAL;
4353 goto out;
4354 }
4355 }
4356 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004357 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
4360 }
4361 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004362 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004363 if (curproxy == &defproxy) {
4364 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004365 err_code |= ERR_ALERT | ERR_FATAL;
4366 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004367 }
4368
Willy Tarreaub80c2302007-11-30 20:51:32 +01004369 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004370 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004371
4372 if (strcmp(args[1], "fail") == 0) {
4373 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004374 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004375 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4376 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004379 }
4380
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004381 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4382 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4383 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004386 }
4387 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4388 }
4389 else {
4390 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_FATAL;
4392 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004393 }
4394 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004395#ifdef TPROXY
4396 else if (!strcmp(args[0], "transparent")) {
4397 /* enable transparent proxy connections */
4398 curproxy->options |= PR_O_TRANSP;
4399 }
4400#endif
4401 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004402 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004403 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004404
Willy Tarreaubaaee002006-06-26 02:48:02 +02004405 if (*(args[1]) == 0) {
4406 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_FATAL;
4408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004409 }
4410 curproxy->maxconn = atol(args[1]);
4411 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004412 else if (!strcmp(args[0], "backlog")) { /* backlog */
4413 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004414 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004415
4416 if (*(args[1]) == 0) {
4417 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004418 err_code |= ERR_ALERT | ERR_FATAL;
4419 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004420 }
4421 curproxy->backlog = atol(args[1]);
4422 }
Willy Tarreau86034312006-12-29 00:10:33 +01004423 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004424 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004426
Willy Tarreau86034312006-12-29 00:10:33 +01004427 if (*(args[1]) == 0) {
4428 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004431 }
4432 curproxy->fullconn = atol(args[1]);
4433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004434 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4435 if (*(args[1]) == 0) {
4436 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004439 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004440 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4441 if (err) {
4442 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4443 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004446 }
4447 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004448 }
4449 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004450 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004451 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004452 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004453
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 if (curproxy == &defproxy) {
4455 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004458 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004459 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004461
Willy Tarreau902636f2013-03-10 19:44:48 +01004462 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004463 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004464 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004465 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004466 goto out;
4467 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004468
4469 proto = protocol_by_family(sk->ss_family);
4470 if (!proto || !proto->connect) {
4471 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4472 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
4475 }
4476
4477 if (port1 != port2) {
4478 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4479 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004482 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004483
4484 if (!port1) {
4485 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4486 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004487 err_code |= ERR_ALERT | ERR_FATAL;
4488 goto out;
4489 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004490
Willy Tarreaud5191e72010-02-09 20:50:45 +01004491 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004492 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004493 }
4494 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004495 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004497
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004498 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4499 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004504 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004505 /**
4506 * The syntax for hash-type config element is
4507 * hash-type {map-based|consistent} [[<algo>] avalanche]
4508 *
4509 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4510 */
4511 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004512
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004513 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4514 err_code |= ERR_WARN;
4515
4516 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004517 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4518 }
4519 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004520 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4521 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004522 else if (strcmp(args[1], "avalanche") == 0) {
4523 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]);
4524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004526 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004527 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004528 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
Bhaskar98634f02013-10-29 23:30:51 -04004532
4533 /* set the hash function to use */
4534 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004535 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004536 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004537
4538 /* if consistent with no argument, then avalanche modifier is also applied */
4539 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4540 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004541 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004542 /* set the hash function */
4543 if (!strcmp(args[2], "sdbm")) {
4544 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4545 }
4546 else if (!strcmp(args[2], "djb2")) {
4547 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004548 } else if (!strcmp(args[2], "wt6")) {
4549 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004550 }
4551 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004552 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 -05004553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
4555 }
4556
4557 /* set the hash modifier */
4558 if (!strcmp(args[3], "avalanche")) {
4559 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4560 }
4561 else if (*args[3]) {
4562 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4563 err_code |= ERR_ALERT | ERR_FATAL;
4564 goto out;
4565 }
Bhaskar98634f02013-10-29 23:30:51 -04004566 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004567 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004568 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004570 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004571 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004572
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004573 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004574 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004575 err_code |= ERR_ALERT | ERR_FATAL;
4576 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004577 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004578 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004579 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580
4581 if (!*args[2]) {
4582 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4583 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004584 err_code |= ERR_ALERT | ERR_FATAL;
4585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004587
4588 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004589 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004590 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4591 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004594 }
4595
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004596 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004597 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004598 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004599 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004600
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004601 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4602 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4603 err_code |= ERR_ALERT | ERR_ABORT;
4604 goto out;
4605 }
4606
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004607 /* the servers are linked backwards first */
4608 newsrv->next = curproxy->srv;
4609 curproxy->srv = newsrv;
4610 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004611 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004612 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004614 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004615 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004616 LIST_INIT(&newsrv->pendconns);
4617 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004618 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004619 newsrv->state = SRV_RUNNING; /* early server setup */
4620 newsrv->last_change = now.tv_sec;
4621 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004623 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004624 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004625 * - IP: => port=+0, relative
4626 * - IP:N => port=N, absolute
4627 * - IP:+N => port=+N, relative
4628 * - IP:-N => port=-N, relative
4629 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004630 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004631 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004632 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004633 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004634 goto out;
4635 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004636
4637 proto = protocol_by_family(sk->ss_family);
4638 if (!proto || !proto->connect) {
4639 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4640 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
4643 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004644
4645 if (!port1 || !port2) {
4646 /* no port specified, +offset, -offset */
4647 newsrv->state |= SRV_MAPPORTS;
4648 }
4649 else if (port1 != port2) {
4650 /* port range */
4651 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4652 file, linenum, args[0], args[1], args[2]);
4653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
4655 }
4656 else {
4657 /* used by checks */
4658 realport = port1;
4659 }
4660
Willy Tarreaud5191e72010-02-09 20:50:45 +01004661 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004662 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4663 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004664
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004665 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004666 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4667 file, linenum, newsrv->addr.ss_family, args[2]);
4668 err_code |= ERR_ALERT | ERR_FATAL;
4669 goto out;
4670 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004671
Simon Hormand60d6912013-11-25 10:46:36 +09004672 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004673 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004674 newsrv->check.inter = curproxy->defsrv.check.inter;
4675 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4676 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004677 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4678 newsrv->agent.port = curproxy->defsrv.agent.port;
4679 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4680 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4681 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004682 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4683 newsrv->minconn = curproxy->defsrv.minconn;
4684 newsrv->maxconn = curproxy->defsrv.maxconn;
4685 newsrv->slowstart = curproxy->defsrv.slowstart;
4686 newsrv->onerror = curproxy->defsrv.onerror;
Willy Tarreauabd03df2014-02-18 10:36:15 +01004687 newsrv->onmarkeddown = curproxy->defsrv.onmarkeddown;
4688 newsrv->onmarkedup = curproxy->defsrv.onmarkedup;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004689 newsrv->consecutive_errors_limit
4690 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004691#ifdef OPENSSL
4692 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4693#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004694 newsrv->uweight = newsrv->iweight
4695 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004696
Simon Horman69d29f92013-02-23 15:14:19 +09004697 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004698 newsrv->check.rise = curproxy->defsrv.check.rise;
4699 newsrv->check.fall = curproxy->defsrv.check.fall;
4700 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004701 newsrv->check.server = newsrv;
4702
Simon Hormand60d6912013-11-25 10:46:36 +09004703 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004704 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4705 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4706 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004707 newsrv->agent.server = newsrv;
4708
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004709 cur_arg = 3;
4710 } else {
4711 newsrv = &curproxy->defsrv;
4712 cur_arg = 1;
4713 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004714
Willy Tarreaubaaee002006-06-26 02:48:02 +02004715 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004716 if (!strcmp(args[cur_arg], "agent-check")) {
4717 global.maxsock++;
4718 do_agent = 1;
4719 cur_arg += 1;
4720 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4721 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4722 if (err) {
4723 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4724 file, linenum, *err, newsrv->id);
4725 err_code |= ERR_ALERT | ERR_FATAL;
4726 goto out;
4727 }
4728 if (val <= 0) {
4729 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4730 file, linenum, val, args[cur_arg], newsrv->id);
4731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
4733 }
4734 newsrv->agent.inter = val;
4735 cur_arg += 2;
4736 }
4737 else if (!strcmp(args[cur_arg], "agent-port")) {
4738 global.maxsock++;
4739 newsrv->agent.port = atol(args[cur_arg + 1]);
4740 cur_arg += 2;
4741 }
4742 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 newsrv->cookie = strdup(args[cur_arg + 1]);
4744 newsrv->cklen = strlen(args[cur_arg + 1]);
4745 cur_arg += 2;
4746 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004747 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004748 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4749 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4750 cur_arg += 2;
4751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004753 if (!*args[cur_arg + 1]) {
4754 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4755 file, linenum, args[cur_arg]);
4756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
4758 }
4759
Simon Horman58c32972013-11-25 10:46:38 +09004760 newsrv->check.rise = atol(args[cur_arg + 1]);
4761 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004762 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4763 file, linenum, args[cur_arg]);
4764 err_code |= ERR_ALERT | ERR_FATAL;
4765 goto out;
4766 }
4767
Simon Horman125d0992013-02-24 17:23:38 +09004768 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004769 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004770 cur_arg += 2;
4771 }
4772 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004773 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004774
4775 if (!*args[cur_arg + 1]) {
4776 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4777 file, linenum, args[cur_arg]);
4778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
4780 }
4781
Simon Horman58c32972013-11-25 10:46:38 +09004782 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004783 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4784 file, linenum, args[cur_arg]);
4785 err_code |= ERR_ALERT | ERR_FATAL;
4786 goto out;
4787 }
4788
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 cur_arg += 2;
4790 }
4791 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004792 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4793 if (err) {
4794 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4795 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004796 err_code |= ERR_ALERT | ERR_FATAL;
4797 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004798 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004799 if (val <= 0) {
4800 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4801 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004804 }
Simon Horman66183002013-02-23 10:16:43 +09004805 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004806 cur_arg += 2;
4807 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004808 else if (!strcmp(args[cur_arg], "fastinter")) {
4809 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4810 if (err) {
4811 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4812 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004815 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004816 if (val <= 0) {
4817 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4818 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004821 }
Simon Horman66183002013-02-23 10:16:43 +09004822 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004823 cur_arg += 2;
4824 }
4825 else if (!strcmp(args[cur_arg], "downinter")) {
4826 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4827 if (err) {
4828 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4829 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004832 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004833 if (val <= 0) {
4834 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4835 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004838 }
Simon Horman66183002013-02-23 10:16:43 +09004839 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004840 cur_arg += 2;
4841 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004842 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004843 struct sockaddr_storage *sk;
4844 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004845 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004846
Willy Tarreau902636f2013-03-10 19:44:48 +01004847 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004848 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004849 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004850 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004851 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004852 goto out;
4853 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004854
4855 proto = protocol_by_family(sk->ss_family);
4856 if (!proto || !proto->connect) {
4857 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004858 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
4861 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004862
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004863 if (port1 != port2) {
4864 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4865 file, linenum, args[cur_arg], args[cur_arg + 1]);
4866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
4869
Simon Horman66183002013-02-23 10:16:43 +09004870 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004871 cur_arg += 2;
4872 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004873 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004874 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004875 cur_arg += 2;
4876 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004877 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 newsrv->state |= SRV_BACKUP;
4879 cur_arg ++;
4880 }
Simon Hormanfa461682011-06-25 09:39:49 +09004881 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4882 newsrv->state |= SRV_NON_STICK;
4883 cur_arg ++;
4884 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004885 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4886 newsrv->state |= SRV_SEND_PROXY;
4887 cur_arg ++;
4888 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004889 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4890 newsrv->check.send_proxy = 1;
4891 cur_arg ++;
4892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893 else if (!strcmp(args[cur_arg], "weight")) {
4894 int w;
4895 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004896 if (w < 0 || w > SRV_UWGHT_MAX) {
4897 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4898 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004899 err_code |= ERR_ALERT | ERR_FATAL;
4900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004901 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004902 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 cur_arg += 2;
4904 }
4905 else if (!strcmp(args[cur_arg], "minconn")) {
4906 newsrv->minconn = atol(args[cur_arg + 1]);
4907 cur_arg += 2;
4908 }
4909 else if (!strcmp(args[cur_arg], "maxconn")) {
4910 newsrv->maxconn = atol(args[cur_arg + 1]);
4911 cur_arg += 2;
4912 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004913 else if (!strcmp(args[cur_arg], "maxqueue")) {
4914 newsrv->maxqueue = atol(args[cur_arg + 1]);
4915 cur_arg += 2;
4916 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004917 else if (!strcmp(args[cur_arg], "slowstart")) {
4918 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004919 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004920 if (err) {
4921 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4922 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004925 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004926 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004927 cur_arg += 2;
4928 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004929 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004930
4931 if (!*args[cur_arg + 1]) {
4932 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4933 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004936 }
4937
4938 newsrv->trackit = strdup(args[cur_arg + 1]);
4939
4940 cur_arg += 2;
4941 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004942 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 global.maxsock++;
4944 do_check = 1;
4945 cur_arg += 1;
4946 }
Willy Tarreau96839092010-03-29 10:02:24 +02004947 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4948 newsrv->state |= SRV_MAINTAIN;
4949 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004950 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004951 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004952 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004953 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004954 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004955 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004956 if (!strcmp(args[cur_arg + 1], "none"))
4957 newsrv->observe = HANA_OBS_NONE;
4958 else if (!strcmp(args[cur_arg + 1], "layer4"))
4959 newsrv->observe = HANA_OBS_LAYER4;
4960 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4961 if (curproxy->mode != PR_MODE_HTTP) {
4962 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4963 file, linenum, args[cur_arg + 1]);
4964 err_code |= ERR_ALERT;
4965 }
4966 newsrv->observe = HANA_OBS_LAYER7;
4967 }
4968 else {
4969 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004970 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004971 file, linenum, args[cur_arg], args[cur_arg + 1]);
4972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
4974 }
4975
4976 cur_arg += 2;
4977 }
4978 else if (!strcmp(args[cur_arg], "on-error")) {
4979 if (!strcmp(args[cur_arg + 1], "fastinter"))
4980 newsrv->onerror = HANA_ONERR_FASTINTER;
4981 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4982 newsrv->onerror = HANA_ONERR_FAILCHK;
4983 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4984 newsrv->onerror = HANA_ONERR_SUDDTH;
4985 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4986 newsrv->onerror = HANA_ONERR_MARKDWN;
4987 else {
4988 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004989 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004990 file, linenum, args[cur_arg], args[cur_arg + 1]);
4991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
4994
4995 cur_arg += 2;
4996 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004997 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4998 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4999 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
5000 else {
5001 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
5002 file, linenum, args[cur_arg], args[cur_arg + 1]);
5003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
5005 }
5006
5007 cur_arg += 2;
5008 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07005009 else if (!strcmp(args[cur_arg], "on-marked-up")) {
5010 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
5011 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
5012 else {
5013 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
5014 file, linenum, args[cur_arg], args[cur_arg + 1]);
5015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
5017 }
5018
5019 cur_arg += 2;
5020 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005021 else if (!strcmp(args[cur_arg], "error-limit")) {
5022 if (!*args[cur_arg + 1]) {
5023 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
5024 file, linenum, args[cur_arg]);
5025 err_code |= ERR_ALERT | ERR_FATAL;
5026 goto out;
5027 }
5028
5029 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
5030
5031 if (newsrv->consecutive_errors_limit <= 0) {
5032 Alert("parsing [%s:%d]: %s has to be > 0.\n",
5033 file, linenum, args[cur_arg]);
5034 err_code |= ERR_ALERT | ERR_FATAL;
5035 goto out;
5036 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01005037 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005038 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005039 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005040 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005041 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005042 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01005043
Willy Tarreaubaaee002006-06-26 02:48:02 +02005044 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01005045 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
5046 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005047 err_code |= ERR_ALERT | ERR_FATAL;
5048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005049 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005050
Willy Tarreauef9a3602012-12-08 22:29:20 +01005051 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01005052 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005053 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005054 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005055 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005056 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005057 goto out;
5058 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005059
5060 proto = protocol_by_family(sk->ss_family);
5061 if (!proto || !proto->connect) {
5062 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5063 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
5066 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005067
Willy Tarreauef9a3602012-12-08 22:29:20 +01005068 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005069
5070 if (port_low != port_high) {
5071 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005072
5073 if (!port_low || !port_high) {
5074 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
5075 file, linenum, args[cur_arg], args[cur_arg + 1]);
5076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
5078 }
5079
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005080 if (port_low <= 0 || port_low > 65535 ||
5081 port_high <= 0 || port_high > 65535 ||
5082 port_low > port_high) {
5083 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
5084 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02005085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005087 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005088 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
5089 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
5090 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005091 }
5092
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005094 while (*(args[cur_arg])) {
5095 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005096#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5097#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005098 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01005099 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
5100 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005103 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005104#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005105 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005106 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01005107 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005110 }
5111 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005112 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5113 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005114 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005115 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5116 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005117 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5118 char *name, *end;
5119
5120 name = args[cur_arg+1] + 7;
5121 while (isspace(*name))
5122 name++;
5123
5124 end = name;
5125 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5126 end++;
5127
Willy Tarreauef9a3602012-12-08 22:29:20 +01005128 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5129 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5130 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5131 newsrv->conn_src.bind_hdr_len = end - name;
5132 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5133 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5134 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005135
5136 /* now look for an occurrence number */
5137 while (isspace(*end))
5138 end++;
5139 if (*end == ',') {
5140 end++;
5141 name = end;
5142 if (*end == '-')
5143 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005144 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005145 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005146 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005147 }
5148
Willy Tarreauef9a3602012-12-08 22:29:20 +01005149 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005150 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5151 " occurrences values smaller than %d.\n",
5152 file, linenum, MAX_HDR_HISTORY);
5153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
5155 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005156 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005157 struct sockaddr_storage *sk;
5158 int port1, port2;
5159
Willy Tarreau902636f2013-03-10 19:44:48 +01005160 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005161 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005162 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005163 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005164 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005165 goto out;
5166 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005167
5168 proto = protocol_by_family(sk->ss_family);
5169 if (!proto || !proto->connect) {
5170 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5171 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
5174 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005175
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005176 if (port1 != port2) {
5177 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5178 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005182 newsrv->conn_src.tproxy_addr = *sk;
5183 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005184 }
5185 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005186#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005187 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005188#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005189 cur_arg += 2;
5190 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005191#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005192 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005193 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005194 err_code |= ERR_ALERT | ERR_FATAL;
5195 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005196#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005197 } /* "usesrc" */
5198
5199 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5200#ifdef SO_BINDTODEVICE
5201 if (!*args[cur_arg + 1]) {
5202 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005206 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005207 free(newsrv->conn_src.iface_name);
5208 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5209 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005210 global.last_checks |= LSTCHK_NETADM;
5211#else
5212 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5213 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005216#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005217 cur_arg += 2;
5218 continue;
5219 }
5220 /* this keyword in not an option of "source" */
5221 break;
5222 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005224 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005225 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5226 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005229 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005231 static int srv_dumped;
5232 struct srv_kw *kw;
5233 char *err;
5234
5235 kw = srv_find_kw(args[cur_arg]);
5236 if (kw) {
5237 char *err = NULL;
5238 int code;
5239
5240 if (!kw->parse) {
5241 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5242 file, linenum, args[0], args[1], args[cur_arg]);
5243 cur_arg += 1 + kw->skip ;
5244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246 }
5247
5248 if (defsrv && !kw->default_ok) {
5249 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5250 file, linenum, args[0], args[1], args[cur_arg]);
5251 cur_arg += 1 + kw->skip ;
5252 err_code |= ERR_ALERT;
5253 continue;
5254 }
5255
5256 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5257 err_code |= code;
5258
5259 if (code) {
5260 if (err && *err) {
5261 indent_msg(&err, 2);
5262 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5263 }
5264 else
5265 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5266 file, linenum, args[0], args[1], args[cur_arg]);
5267 if (code & ERR_FATAL) {
5268 free(err);
5269 cur_arg += 1 + kw->skip;
5270 goto out;
5271 }
5272 }
5273 free(err);
5274 cur_arg += 1 + kw->skip;
5275 continue;
5276 }
5277
5278 err = NULL;
5279 if (!srv_dumped) {
5280 srv_dump_kws(&err);
5281 indent_msg(&err, 4);
5282 srv_dumped = 1;
5283 }
5284
5285 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5286 file, linenum, args[0], args[1], args[cur_arg],
5287 err ? " Registered keywords :" : "", err ? err : "");
5288 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005289
Willy Tarreau93893792009-07-23 13:19:11 +02005290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
5293 }
5294
Simon Horman8c3d0be2013-11-25 10:46:40 +09005295 /* Set initial drain state using now-configured weight */
5296 set_server_drain_state(newsrv);
5297
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005299 int ret;
5300
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005301 if (newsrv->trackit) {
5302 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5303 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005306 }
5307
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005308 /* If neither a port nor an addr was specified and no check transport
5309 * layer is forced, then the transport layer used by the checks is the
5310 * same as for the production traffic. Otherwise we use raw_sock by
5311 * default, unless one is specified.
5312 */
Simon Horman66183002013-02-23 10:16:43 +09005313 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005314#ifdef USE_OPENSSL
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005315 newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
Willy Tarreau71516332012-10-10 23:01:14 +02005316#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005317 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5318 }
Simon Horman66183002013-02-23 10:16:43 +09005319 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005320 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005321 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005322
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005323 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005324 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005325
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005326 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005327 /* not yet valid, because no port was set on
5328 * the server either. We'll check if we have
5329 * a known port on the first listener.
5330 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005331 struct listener *l;
5332
5333 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005334 newsrv->check.port = get_host_port(&l->addr);
5335 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005336 break;
5337 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005338 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005339 /*
5340 * We need at least a service port, a check port or the first tcp-check rule must
5341 * be a 'connect' one
5342 */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005343 if (!newsrv->check.port) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005344 struct tcpcheck_rule *n = NULL, *r = NULL;
5345 struct list *l;
5346
5347 r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
5348 if (!r) {
5349 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5350 file, linenum, newsrv->id);
5351 err_code |= ERR_ALERT | ERR_FATAL;
5352 goto out;
5353 }
5354 if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
5355 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",
5356 file, linenum, newsrv->id);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360 else {
5361 /* scan the tcp-check ruleset to ensure a port has been configured */
5362 l = &newsrv->proxy->tcpcheck_rules;
5363 list_for_each_entry(n, l, list) {
5364 r = (struct tcpcheck_rule *)n->list.p;
5365 if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
5366 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",
5367 file, linenum, newsrv->id);
5368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
5370 }
5371 }
5372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005374
Willy Tarreau2f075e92013-12-03 11:11:34 +01005375 /* note: check type will be set during the config review phase */
5376 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005377 if (ret) {
5378 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005379 goto out;
5380 }
5381
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005382 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005383 }
5384
Simon Hormand60d6912013-11-25 10:46:36 +09005385 if (do_agent) {
5386 int ret;
5387
5388 if (!newsrv->agent.port) {
5389 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5390 file, linenum, newsrv->id);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
5393 }
5394
5395 if (!newsrv->agent.inter)
5396 newsrv->agent.inter = newsrv->check.inter;
5397
5398 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5399 if (ret) {
5400 err_code |= ret;
5401 goto out;
5402 }
5403
Willy Tarreau33434322013-12-11 21:15:19 +01005404 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005405 }
5406
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005407 if (!defsrv) {
5408 if (newsrv->state & SRV_BACKUP)
5409 curproxy->srv_bck++;
5410 else
5411 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005412
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005413 newsrv->prev_state = newsrv->state;
5414 }
William Lallemanda73203e2012-03-12 12:48:57 +01005415 }
5416
5417 else if (strcmp(args[0], "unique-id-format") == 0) {
5418 if (!*(args[1])) {
5419 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
5422 }
William Lallemand3203ff42012-11-11 17:30:56 +01005423 if (*(args[2])) {
5424 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005428 free(curproxy->conf.uniqueid_format_string);
5429 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005430
Willy Tarreau62a61232013-04-12 18:13:46 +02005431 free(curproxy->conf.uif_file);
5432 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5433 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005434 }
William Lallemanda73203e2012-03-12 12:48:57 +01005435
5436 else if (strcmp(args[0], "unique-id-header") == 0) {
5437 if (!*(args[1])) {
5438 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
5442 free(curproxy->header_unique_id);
5443 curproxy->header_unique_id = strdup(args[1]);
5444 }
5445
William Lallemand723b73a2012-02-08 16:37:49 +01005446 else if (strcmp(args[0], "log-format") == 0) {
5447 if (!*(args[1])) {
5448 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 }
William Lallemand3203ff42012-11-11 17:30:56 +01005452 if (*(args[2])) {
5453 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5454 err_code |= ERR_ALERT | ERR_FATAL;
5455 goto out;
5456 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005457
Willy Tarreau62a61232013-04-12 18:13:46 +02005458 if (curproxy->conf.logformat_string != default_http_log_format &&
5459 curproxy->conf.logformat_string != default_tcp_log_format &&
5460 curproxy->conf.logformat_string != clf_http_log_format)
5461 free(curproxy->conf.logformat_string);
5462 curproxy->conf.logformat_string = strdup(args[1]);
5463
5464 free(curproxy->conf.lfs_file);
5465 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5466 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005467
5468 /* get a chance to improve log-format error reporting by
5469 * reporting the correct line-number when possible.
5470 */
5471 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5472 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5473 file, linenum, curproxy->id);
5474 err_code |= ERR_WARN;
5475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005476 }
William Lallemand723b73a2012-02-08 16:37:49 +01005477
William Lallemand0f99e342011-10-12 17:50:54 +02005478 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5479 /* delete previous herited or defined syslog servers */
5480 struct logsrv *back;
5481
5482 if (*(args[1]) != 0) {
5483 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
5486 }
5487
William Lallemand723b73a2012-02-08 16:37:49 +01005488 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5489 LIST_DEL(&tmplogsrv->list);
5490 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005491 }
5492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005494 struct logsrv *logsrv;
5495
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005497 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005498 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005499 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005500 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005501 LIST_INIT(&node->list);
5502 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005504 }
5505 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005506 struct sockaddr_storage *sk;
5507 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005508
5509 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510
William Lallemand0f99e342011-10-12 17:50:54 +02005511 logsrv->facility = get_log_facility(args[2]);
5512 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005513 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 }
5518
William Lallemand0f99e342011-10-12 17:50:54 +02005519 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005520 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005521 logsrv->level = get_log_level(args[3]);
5522 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
5526
Willy Tarreaubaaee002006-06-26 02:48:02 +02005527 }
5528 }
5529
William Lallemand0f99e342011-10-12 17:50:54 +02005530 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005531 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005532 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005533 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005534 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
5537
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005538 }
5539 }
5540
Willy Tarreau902636f2013-03-10 19:44:48 +01005541 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005542 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005543 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005544 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005545 goto out;
5546 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005547
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005548 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005549
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005550 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005551 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 Tarreau6d03cc32013-02-20 17:26:02 +01005558 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005559 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005560 }
William Lallemand0f99e342011-10-12 17:50:54 +02005561
5562 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005563 }
5564 else {
5565 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5566 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 }
5570 }
5571 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005572 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005573 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005574 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005575 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005576
Willy Tarreau977b8e42006-12-29 14:19:17 +01005577 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005579
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005581 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5582 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005585 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005586
5587 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005588 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5589 free(curproxy->conn_src.iface_name);
5590 curproxy->conn_src.iface_name = NULL;
5591 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005592
Willy Tarreau902636f2013-03-10 19:44:48 +01005593 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005594 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005595 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005596 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005597 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005598 goto out;
5599 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005600
5601 proto = protocol_by_family(sk->ss_family);
5602 if (!proto || !proto->connect) {
5603 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005604 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005608
5609 if (port1 != port2) {
5610 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5611 file, linenum, args[0], args[1]);
5612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
5614 }
5615
Willy Tarreauef9a3602012-12-08 22:29:20 +01005616 curproxy->conn_src.source_addr = *sk;
5617 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005618
5619 cur_arg = 2;
5620 while (*(args[cur_arg])) {
5621 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005622#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5623#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005624 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005625 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5626 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005627 err_code |= ERR_ALERT | ERR_FATAL;
5628 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005629 }
5630#endif
5631 if (!*args[cur_arg + 1]) {
5632 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5633 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005634 err_code |= ERR_ALERT | ERR_FATAL;
5635 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005636 }
5637
5638 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005639 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5640 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005641 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005642 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5643 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005644 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5645 char *name, *end;
5646
5647 name = args[cur_arg+1] + 7;
5648 while (isspace(*name))
5649 name++;
5650
5651 end = name;
5652 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5653 end++;
5654
Willy Tarreauef9a3602012-12-08 22:29:20 +01005655 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5656 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5657 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5658 curproxy->conn_src.bind_hdr_len = end - name;
5659 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5660 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5661 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005662
5663 /* now look for an occurrence number */
5664 while (isspace(*end))
5665 end++;
5666 if (*end == ',') {
5667 end++;
5668 name = end;
5669 if (*end == '-')
5670 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005671 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005672 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005673 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005674 }
5675
Willy Tarreauef9a3602012-12-08 22:29:20 +01005676 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005677 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5678 " occurrences values smaller than %d.\n",
5679 file, linenum, MAX_HDR_HISTORY);
5680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005683 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005684 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005685
Willy Tarreau902636f2013-03-10 19:44:48 +01005686 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005687 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005688 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005689 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005690 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005691 goto out;
5692 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005693
5694 proto = protocol_by_family(sk->ss_family);
5695 if (!proto || !proto->connect) {
5696 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5697 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005701
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005702 if (port1 != port2) {
5703 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5704 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
5707 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005708 curproxy->conn_src.tproxy_addr = *sk;
5709 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005710 }
5711 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005712#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005713 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005714#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005715#else /* no TPROXY support */
5716 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005717 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005720#endif
5721 cur_arg += 2;
5722 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005723 }
5724
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005725 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5726#ifdef SO_BINDTODEVICE
5727 if (!*args[cur_arg + 1]) {
5728 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5729 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005732 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005733 free(curproxy->conn_src.iface_name);
5734 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5735 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005736 global.last_checks |= LSTCHK_NETADM;
5737#else
5738 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5739 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005740 err_code |= ERR_ALERT | ERR_FATAL;
5741 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005742#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005743 cur_arg += 2;
5744 continue;
5745 }
5746 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005747 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_ALERT | ERR_FATAL;
5749 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005751 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005752 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5753 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5754 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005755 err_code |= ERR_ALERT | ERR_FATAL;
5756 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005759 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5761 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_ALERT | ERR_FATAL;
5763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005765
5766 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005767 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005768 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005769 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005771 }
5772 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005773 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005774 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005775 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005776 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 }
5779 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005780 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005781 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005782 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005783 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005784 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005785 }
5786 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005787 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005788 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005789 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005790 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
5793 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005794 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005795 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005796 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005797 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005798 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005799 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005800 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005801 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005802 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005803 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005804 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005805 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005806 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005807 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005808 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005809 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005810 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005811 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005812 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005813 }
5814 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005815 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005816 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005817 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005818 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005819 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005820 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005822 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5824 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 Tarreauade5ec42010-01-28 19:33:49 +01005828
5829 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005830 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005831 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005832 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005834 }
5835 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005836 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005837 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005838 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005839 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841 }
5842 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005843 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005844 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005845 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005846 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 }
5849 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005850 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005851 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005852 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005853 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005854 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 }
5856 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005857 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005858 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005859 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005860 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005863 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005864 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005865 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005866 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005867 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005868 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005871 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005872
Willy Tarreaubaaee002006-06-26 02:48:02 +02005873 if (curproxy == &defproxy) {
5874 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005875 err_code |= ERR_ALERT | ERR_FATAL;
5876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005878 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005879 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 if (*(args[1]) == 0) {
5882 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005883 err_code |= ERR_ALERT | ERR_FATAL;
5884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005885 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005886
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005887 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005888 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5889 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5890 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
5893 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005894 err_code |= warnif_cond_conflicts(cond,
5895 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5896 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005897 }
5898 else if (*args[2]) {
5899 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5900 file, linenum, args[0], args[2]);
5901 err_code |= ERR_ALERT | ERR_FATAL;
5902 goto out;
5903 }
5904
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005905 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005906 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005907 wl->s = strdup(args[1]);
5908 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005909 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 }
5911 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005912 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5914 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005915 err_code |= ERR_ALERT | ERR_FATAL;
5916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005917 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005918
Willy Tarreauade5ec42010-01-28 19:33:49 +01005919 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005920 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005921 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005922 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 }
5925 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005926 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005927 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005928 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005929 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005931 }
5932 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005934 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005935 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938 }
5939 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005940 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005941 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005943 err_code |= ERR_ALERT | ERR_FATAL;
5944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005945 }
5946
Willy Tarreauade5ec42010-01-28 19:33:49 +01005947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005948 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005949 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005952 }
5953 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005955 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005956 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005959 }
5960 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005962 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005966 }
5967 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005968 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005969
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 if (curproxy == &defproxy) {
5971 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005974 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005975 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005976 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 if (*(args[1]) == 0) {
5979 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005980 err_code |= ERR_ALERT | ERR_FATAL;
5981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005982 }
5983
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005984 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005985 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5986 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5987 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005988 err_code |= ERR_ALERT | ERR_FATAL;
5989 goto out;
5990 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005991 err_code |= warnif_cond_conflicts(cond,
5992 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5993 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005994 }
5995 else if (*args[2]) {
5996 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5997 file, linenum, args[0], args[2]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006002 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006003 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006004 wl->s = strdup(args[1]);
6005 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006006 }
6007 else if (!strcmp(args[0], "errorloc") ||
6008 !strcmp(args[0], "errorloc302") ||
6009 !strcmp(args[0], "errorloc303")) { /* error location */
6010 int errnum, errlen;
6011 char *err;
6012
Willy Tarreau977b8e42006-12-29 14:19:17 +01006013 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006014 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006015
Willy Tarreaubaaee002006-06-26 02:48:02 +02006016 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006017 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006018 err_code |= ERR_ALERT | ERR_FATAL;
6019 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020 }
6021
6022 errnum = atol(args[1]);
6023 if (!strcmp(args[0], "errorloc303")) {
6024 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
6025 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
6026 } else {
6027 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
6028 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
6029 }
6030
Willy Tarreau0f772532006-12-23 20:51:41 +01006031 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6032 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006033 chunk_destroy(&curproxy->errmsg[rc]);
6034 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006035 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006036 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006037 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006038
6039 if (rc >= HTTP_ERR_SIZE) {
6040 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6041 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006042 free(err);
6043 }
6044 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006045 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6046 int errnum, errlen, fd;
6047 char *err;
6048 struct stat stat;
6049
6050 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006051 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006052
6053 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006054 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006055 err_code |= ERR_ALERT | ERR_FATAL;
6056 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006057 }
6058
6059 fd = open(args[2], O_RDONLY);
6060 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6061 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6062 file, linenum, args[2], args[1]);
6063 if (fd >= 0)
6064 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006067 }
6068
Willy Tarreau27a674e2009-08-17 07:23:33 +02006069 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006070 errlen = stat.st_size;
6071 } else {
6072 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006073 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006074 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006075 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006076 }
6077
6078 err = malloc(errlen); /* malloc() must succeed during parsing */
6079 errnum = read(fd, err, errlen);
6080 if (errnum != errlen) {
6081 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6082 file, linenum, args[2], args[1]);
6083 close(fd);
6084 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006085 err_code |= ERR_ALERT | ERR_FATAL;
6086 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006087 }
6088 close(fd);
6089
6090 errnum = atol(args[1]);
6091 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6092 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006093 chunk_destroy(&curproxy->errmsg[rc]);
6094 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006095 break;
6096 }
6097 }
6098
6099 if (rc >= HTTP_ERR_SIZE) {
6100 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6101 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006102 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006103 free(err);
6104 }
6105 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006106 else if (!strcmp(args[0], "compression")) {
6107 struct comp *comp;
6108 if (curproxy->comp == NULL) {
6109 comp = calloc(1, sizeof(struct comp));
6110 curproxy->comp = comp;
6111 } else {
6112 comp = curproxy->comp;
6113 }
6114
6115 if (!strcmp(args[1], "algo")) {
6116 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006117 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006118
William Lallemand82fe75c2012-10-23 10:25:10 +02006119 cur_arg = 2;
6120 if (!*args[cur_arg]) {
6121 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6122 file, linenum, args[0]);
6123 err_code |= ERR_ALERT | ERR_FATAL;
6124 goto out;
6125 }
6126 while (*(args[cur_arg])) {
6127 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6128 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6129 file, linenum, args[0], args[cur_arg]);
6130 err_code |= ERR_ALERT | ERR_FATAL;
6131 goto out;
6132 }
William Lallemand552df672012-11-07 13:21:47 +01006133 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6134 curproxy->comp->algos->end(&ctx);
6135 } else {
6136 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6137 file, linenum, args[0], args[cur_arg]);
6138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
6140 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006141 cur_arg ++;
6142 continue;
6143 }
6144 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006145 else if (!strcmp(args[1], "offload")) {
6146 comp->offload = 1;
6147 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006148 else if (!strcmp(args[1], "type")) {
6149 int cur_arg;
6150 cur_arg = 2;
6151 if (!*args[cur_arg]) {
6152 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6153 file, linenum, args[0]);
6154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
6156 }
6157 while (*(args[cur_arg])) {
6158 comp_append_type(comp, args[cur_arg]);
6159 cur_arg ++;
6160 continue;
6161 }
6162 }
6163 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006164 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006165 file, linenum, args[0]);
6166 err_code |= ERR_ALERT | ERR_FATAL;
6167 goto out;
6168 }
6169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006171 struct cfg_kw_list *kwl;
6172 int index;
6173
6174 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6175 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6176 if (kwl->kw[index].section != CFG_LISTEN)
6177 continue;
6178 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6179 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006180 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006181 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006182 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006183 err_code |= ERR_ALERT | ERR_FATAL;
6184 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006185 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006186 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006187 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006188 err_code |= ERR_WARN;
6189 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006190 }
Willy Tarreau93893792009-07-23 13:19:11 +02006191 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006192 }
6193 }
6194 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006195
Willy Tarreau6daf3432008-01-22 16:44:08 +01006196 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006197 err_code |= ERR_ALERT | ERR_FATAL;
6198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 }
Willy Tarreau93893792009-07-23 13:19:11 +02006200 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006201 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006202 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006203}
6204
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006205int
6206cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6207{
6208
6209 int err_code = 0;
6210 const char *err;
6211
6212 if (!strcmp(args[0], "userlist")) { /* new userlist */
6213 struct userlist *newul;
6214
6215 if (!*args[1]) {
6216 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6217 file, linenum, args[0]);
6218 err_code |= ERR_ALERT | ERR_FATAL;
6219 goto out;
6220 }
6221
6222 err = invalid_char(args[1]);
6223 if (err) {
6224 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6225 file, linenum, *err, args[0], args[1]);
6226 err_code |= ERR_ALERT | ERR_FATAL;
6227 goto out;
6228 }
6229
6230 for (newul = userlist; newul; newul = newul->next)
6231 if (!strcmp(newul->name, args[1])) {
6232 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6233 file, linenum, args[1]);
6234 err_code |= ERR_WARN;
6235 goto out;
6236 }
6237
6238 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6239 if (!newul) {
6240 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6241 err_code |= ERR_ALERT | ERR_ABORT;
6242 goto out;
6243 }
6244
6245 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6246 newul->name = strdup(args[1]);
6247
6248 if (!newul->groupusers | !newul->name) {
6249 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6250 err_code |= ERR_ALERT | ERR_ABORT;
6251 goto out;
6252 }
6253
6254 newul->next = userlist;
6255 userlist = newul;
6256
6257 } else if (!strcmp(args[0], "group")) { /* new group */
6258 int cur_arg, i;
6259 const char *err;
6260
6261 if (!*args[1]) {
6262 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6263 file, linenum, args[0]);
6264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
6266 }
6267
6268 err = invalid_char(args[1]);
6269 if (err) {
6270 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6271 file, linenum, *err, args[0], args[1]);
6272 err_code |= ERR_ALERT | ERR_FATAL;
6273 goto out;
6274 }
6275
6276 for(i = 0; i < userlist->grpcnt; i++)
6277 if (!strcmp(userlist->groups[i], args[1])) {
6278 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6279 file, linenum, args[1], userlist->name);
6280 err_code |= ERR_ALERT;
6281 goto out;
6282 }
6283
6284 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6285 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6286 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6287 err_code |= ERR_ALERT | ERR_FATAL;
6288 goto out;
6289 }
6290
6291 cur_arg = 2;
6292
6293 while (*args[cur_arg]) {
6294 if (!strcmp(args[cur_arg], "users")) {
6295 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6296 cur_arg += 2;
6297 continue;
6298 } else {
6299 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6300 file, linenum, args[0]);
6301 err_code |= ERR_ALERT | ERR_FATAL;
6302 goto out;
6303 }
6304 }
6305
6306 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6307 } else if (!strcmp(args[0], "user")) { /* new user */
6308 struct auth_users *newuser;
6309 int cur_arg;
6310
6311 if (!*args[1]) {
6312 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6313 file, linenum, args[0]);
6314 err_code |= ERR_ALERT | ERR_FATAL;
6315 goto out;
6316 }
6317
6318 for (newuser = userlist->users; newuser; newuser = newuser->next)
6319 if (!strcmp(newuser->user, args[1])) {
6320 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6321 file, linenum, args[1], userlist->name);
6322 err_code |= ERR_ALERT;
6323 goto out;
6324 }
6325
6326 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6327 if (!newuser) {
6328 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6329 err_code |= ERR_ALERT | ERR_ABORT;
6330 goto out;
6331 }
6332
6333 newuser->user = strdup(args[1]);
6334
6335 newuser->next = userlist->users;
6336 userlist->users = newuser;
6337
6338 cur_arg = 2;
6339
6340 while (*args[cur_arg]) {
6341 if (!strcmp(args[cur_arg], "password")) {
6342#ifndef CONFIG_HAP_CRYPT
6343 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6344 file, linenum);
6345 err_code |= ERR_ALERT;
6346#endif
6347 newuser->pass = strdup(args[cur_arg + 1]);
6348 cur_arg += 2;
6349 continue;
6350 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6351 newuser->pass = strdup(args[cur_arg + 1]);
6352 newuser->flags |= AU_O_INSECURE;
6353 cur_arg += 2;
6354 continue;
6355 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006356 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006357 cur_arg += 2;
6358 continue;
6359 } else {
6360 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6361 file, linenum, args[0]);
6362 err_code |= ERR_ALERT | ERR_FATAL;
6363 goto out;
6364 }
6365 }
6366 } else {
6367 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6368 err_code |= ERR_ALERT | ERR_FATAL;
6369 }
6370
6371out:
6372 return err_code;
6373}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374
6375/*
6376 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006377 * Returns the error code, 0 if OK, or any combination of :
6378 * - ERR_ABORT: must abort ASAP
6379 * - ERR_FATAL: we can continue parsing but not start the service
6380 * - ERR_WARN: a warning has been emitted
6381 * - ERR_ALERT: an alert has been emitted
6382 * Only the two first ones can stop processing, the two others are just
6383 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006385int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006387 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 FILE *f;
6389 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006391 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392
Willy Tarreaubaaee002006-06-26 02:48:02 +02006393 if ((f=fopen(file,"r")) == NULL)
6394 return -1;
6395
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006396 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006397 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006398 char *end;
6399 char *args[MAX_LINE_ARGS + 1];
6400 char *line = thisline;
6401
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 linenum++;
6403
6404 end = line + strlen(line);
6405
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006406 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6407 /* Check if we reached the limit and the last char is not \n.
6408 * Watch out for the last line without the terminating '\n'!
6409 */
6410 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006411 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006412 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006413 }
6414
Willy Tarreaubaaee002006-06-26 02:48:02 +02006415 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006416 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006417 line++;
6418
6419 arg = 0;
6420 args[arg] = line;
6421
6422 while (*line && arg < MAX_LINE_ARGS) {
6423 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6424 * C equivalent value. Other combinations left unchanged (eg: \1).
6425 */
6426 if (*line == '\\') {
6427 int skip = 0;
6428 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6429 *line = line[1];
6430 skip = 1;
6431 }
6432 else if (line[1] == 'r') {
6433 *line = '\r';
6434 skip = 1;
6435 }
6436 else if (line[1] == 'n') {
6437 *line = '\n';
6438 skip = 1;
6439 }
6440 else if (line[1] == 't') {
6441 *line = '\t';
6442 skip = 1;
6443 }
6444 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006445 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006446 unsigned char hex1, hex2;
6447 hex1 = toupper(line[2]) - '0';
6448 hex2 = toupper(line[3]) - '0';
6449 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6450 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6451 *line = (hex1<<4) + hex2;
6452 skip = 3;
6453 }
6454 else {
6455 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006456 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006457 }
6458 }
6459 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006460 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461 end -= skip;
6462 }
6463 line++;
6464 }
6465 else if (*line == '#' || *line == '\n' || *line == '\r') {
6466 /* end of string, end of loop */
6467 *line = 0;
6468 break;
6469 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006470 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006472 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006473 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 line++;
6475 args[++arg] = line;
6476 }
6477 else {
6478 line++;
6479 }
6480 }
6481
6482 /* empty line */
6483 if (!**args)
6484 continue;
6485
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006486 if (*line) {
6487 /* we had to stop due to too many args.
6488 * Let's terminate the string, print the offending part then cut the
6489 * last arg.
6490 */
6491 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6492 line++;
6493 *line = '\0';
6494
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006495 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006496 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006497 err_code |= ERR_ALERT | ERR_FATAL;
6498 args[arg] = line;
6499 }
6500
Willy Tarreau540abe42007-05-02 20:50:16 +02006501 /* zero out remaining args and ensure that at least one entry
6502 * is zeroed out.
6503 */
6504 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006505 args[arg] = line;
6506 }
6507
Willy Tarreau3842f002009-06-14 11:39:52 +02006508 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006509 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006510 char *tmp;
6511
Willy Tarreau3842f002009-06-14 11:39:52 +02006512 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006513 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006514 for (arg=0; *args[arg+1]; arg++)
6515 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006516 *tmp = '\0'; // fix the next arg to \0
6517 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006518 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006519 else if (!strcmp(args[0], "default")) {
6520 kwm = KWM_DEF;
6521 for (arg=0; *args[arg+1]; arg++)
6522 args[arg] = args[arg+1]; // shift args after inversion
6523 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006524
William Lallemand0f99e342011-10-12 17:50:54 +02006525 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6526 strcmp(args[0], "log") != 0) {
6527 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006528 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006529 }
6530
Willy Tarreau977b8e42006-12-29 14:19:17 +01006531 if (!strcmp(args[0], "listen") ||
6532 !strcmp(args[0], "frontend") ||
6533 !strcmp(args[0], "backend") ||
6534 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006535 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006536 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006537 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006538 cursection = strdup(args[0]);
6539 }
6540 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006542 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006543 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006544 }
6545 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006546 confsect = CFG_USERLIST;
6547 free(cursection);
6548 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006549 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006550 else if (!strcmp(args[0], "peers")) {
6551 confsect = CFG_PEERS;
6552 free(cursection);
6553 cursection = strdup(args[0]);
6554 }
6555
Willy Tarreaubaaee002006-06-26 02:48:02 +02006556 /* else it's a section keyword */
6557
6558 switch (confsect) {
6559 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006560 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561 break;
6562 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006563 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006564 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006565 case CFG_USERLIST:
6566 err_code |= cfg_parse_users(file, linenum, args, kwm);
6567 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006568 case CFG_PEERS:
6569 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6570 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006571 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006572 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006573 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006574 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006575
6576 if (err_code & ERR_ABORT)
6577 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006579 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006580 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006582 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006583}
6584
Willy Tarreaubb925012009-07-23 13:36:36 +02006585/*
6586 * Returns the error code, 0 if OK, or any combination of :
6587 * - ERR_ABORT: must abort ASAP
6588 * - ERR_FATAL: we can continue parsing but not start the service
6589 * - ERR_WARN: a warning has been emitted
6590 * - ERR_ALERT: an alert has been emitted
6591 * Only the two first ones can stop processing, the two others are just
6592 * indicators.
6593 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006594int check_config_validity()
6595{
6596 int cfgerr = 0;
6597 struct proxy *curproxy = NULL;
6598 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006599 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006600 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006601 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006602 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006603
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006604 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 /*
6606 * Now, check for the integrity of all that we have collected.
6607 */
6608
6609 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006610 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611
Willy Tarreau193b8c62012-11-22 00:17:38 +01006612 if (!global.tune.max_http_hdr)
6613 global.tune.max_http_hdr = MAX_HTTP_HDR;
6614
6615 if (!global.tune.cookie_len)
6616 global.tune.cookie_len = CAPTURE_LEN;
6617
6618 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6619
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006620 /* first, we will invert the proxy list order */
6621 curproxy = NULL;
6622 while (proxy) {
6623 struct proxy *next;
6624
6625 next = proxy->next;
6626 proxy->next = curproxy;
6627 curproxy = proxy;
6628 if (!next)
6629 break;
6630 proxy = next;
6631 }
6632
Willy Tarreaubaaee002006-06-26 02:48:02 +02006633 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006634 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006635 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006636 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006637 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006638 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006639 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006640 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006641
Willy Tarreau050536d2012-10-04 08:47:34 +02006642 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006643 /* proxy ID not set, use automatic numbering with first
6644 * spare entry starting with next_pxid.
6645 */
6646 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6647 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6648 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006649 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006650 next_pxid++;
6651
Willy Tarreau55ea7572007-06-17 19:56:27 +02006652
Willy Tarreaubaaee002006-06-26 02:48:02 +02006653 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006654 /* ensure we don't keep listeners uselessly bound */
6655 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006656 curproxy = curproxy->next;
6657 continue;
6658 }
6659
Willy Tarreau16a21472012-11-19 12:39:59 +01006660 /* number of processes this proxy is bound to */
6661 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6662
Willy Tarreauff01a212009-03-15 13:46:16 +01006663 switch (curproxy->mode) {
6664 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006665 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006666 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006667 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6668 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006669 cfgerr++;
6670 }
6671
6672 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006673 Warning("config : servers will be ignored for %s '%s'.\n",
6674 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006675 break;
6676
6677 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006678 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006679 break;
6680
6681 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006682 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006683 break;
6684 }
6685
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006686 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006687 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006688 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006689 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6690 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006691 cfgerr++;
6692 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006693#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006694 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006695 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6696 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006697 cfgerr++;
6698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006699#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006700 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006701 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6702 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006703 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006704 }
6705 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006706 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006707 /* If no LB algo is set in a backend, and we're not in
6708 * transparent mode, dispatch mode nor proxy mode, we
6709 * want to use balance roundrobin by default.
6710 */
6711 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6712 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006713 }
6714 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006715
Willy Tarreau1620ec32011-08-06 17:05:02 +02006716 if (curproxy->options & PR_O_DISPATCH)
6717 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6718 else if (curproxy->options & PR_O_HTTP_PROXY)
6719 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6720 else if (curproxy->options & PR_O_TRANSP)
6721 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006722
Willy Tarreau1620ec32011-08-06 17:05:02 +02006723 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6724 if (curproxy->options & PR_O_DISABLE404) {
6725 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6726 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6727 err_code |= ERR_WARN;
6728 curproxy->options &= ~PR_O_DISABLE404;
6729 }
6730 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6731 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6732 "send-state", proxy_type_str(curproxy), curproxy->id);
6733 err_code |= ERR_WARN;
6734 curproxy->options &= ~PR_O2_CHK_SNDST;
6735 }
Willy Tarreauef781042010-01-27 11:53:01 +01006736 }
6737
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006738 /* if a default backend was specified, let's find it */
6739 if (curproxy->defbe.name) {
6740 struct proxy *target;
6741
Alex Williams96532db2009-11-01 21:27:13 -05006742 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006743 if (!target) {
6744 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6745 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006746 cfgerr++;
6747 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006748 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6749 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006750 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006751 } else {
6752 free(curproxy->defbe.name);
6753 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006754 /* we force the backend to be present on at least all of
6755 * the frontend's processes.
6756 */
6757 target->bind_proc = curproxy->bind_proc ?
6758 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006759
6760 /* Emit a warning if this proxy also has some servers */
6761 if (curproxy->srv) {
6762 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6763 curproxy->id);
6764 err_code |= ERR_WARN;
6765 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006766 }
6767 }
6768
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006769 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006770 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6771 /* map jump target for ACT_SETBE in req_rep chain */
6772 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006773 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006774 struct proxy *target;
6775
Willy Tarreaua496b602006-12-17 23:15:24 +01006776 if (exp->action != ACT_SETBE)
6777 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006778
Alex Williams96532db2009-11-01 21:27:13 -05006779 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006780 if (!target) {
6781 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6782 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006783 cfgerr++;
6784 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006785 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6786 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006787 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006788 } else {
6789 free((void *)exp->replace);
6790 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006791 /* we force the backend to be present on at least all of
6792 * the frontend's processes.
6793 */
6794 target->bind_proc = curproxy->bind_proc ?
6795 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006796 }
6797 }
6798 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006799
6800 /* find the target proxy for 'use_backend' rules */
6801 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006802 struct proxy *target;
6803
Alex Williams96532db2009-11-01 21:27:13 -05006804 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006805
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006806 if (!target) {
6807 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6808 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006809 cfgerr++;
6810 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006811 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6812 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006813 cfgerr++;
6814 } else {
6815 free((void *)rule->be.name);
6816 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006817 /* we force the backend to be present on at least all of
6818 * the frontend's processes.
6819 */
6820 target->bind_proc = curproxy->bind_proc ?
6821 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006822 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006823 }
6824
6825 /* find the target proxy for 'use_backend' rules */
6826 list_for_each_entry(srule, &curproxy->server_rules, list) {
6827 struct server *target = findserver(curproxy, srule->srv.name);
6828
6829 if (!target) {
6830 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6831 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6832 cfgerr++;
6833 continue;
6834 }
6835 free((void *)srule->srv.name);
6836 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006837 }
6838
Emeric Brunb982a3d2010-01-04 15:45:53 +01006839 /* find the target table for 'stick' rules */
6840 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6841 struct proxy *target;
6842
Emeric Brun1d33b292010-01-04 15:47:17 +01006843 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6844 if (mrule->flags & STK_IS_STORE)
6845 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6846
Emeric Brunb982a3d2010-01-04 15:45:53 +01006847 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006848 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006849 else
6850 target = curproxy;
6851
6852 if (!target) {
6853 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6854 curproxy->id, mrule->table.name);
6855 cfgerr++;
6856 }
6857 else if (target->table.size == 0) {
6858 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6859 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6860 cfgerr++;
6861 }
Willy Tarreau12785782012-04-27 21:37:17 +02006862 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6863 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006864 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6865 cfgerr++;
6866 }
6867 else {
6868 free((void *)mrule->table.name);
6869 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006870 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006871 }
6872 }
6873
6874 /* find the target table for 'store response' rules */
6875 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6876 struct proxy *target;
6877
Emeric Brun1d33b292010-01-04 15:47:17 +01006878 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6879
Emeric Brunb982a3d2010-01-04 15:45:53 +01006880 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006881 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006882 else
6883 target = curproxy;
6884
6885 if (!target) {
6886 Alert("Proxy '%s': unable to find store table '%s'.\n",
6887 curproxy->id, mrule->table.name);
6888 cfgerr++;
6889 }
6890 else if (target->table.size == 0) {
6891 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6892 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6893 cfgerr++;
6894 }
Willy Tarreau12785782012-04-27 21:37:17 +02006895 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6896 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006897 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6898 cfgerr++;
6899 }
6900 else {
6901 free((void *)mrule->table.name);
6902 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006903 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006904 }
6905 }
6906
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006907 /* find the target table for 'tcp-request' layer 4 rules */
6908 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6909 struct proxy *target;
6910
Willy Tarreaub4c84932013-07-23 19:15:30 +02006911 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006912 continue;
6913
6914 if (trule->act_prm.trk_ctr.table.n)
6915 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6916 else
6917 target = curproxy;
6918
6919 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006920 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6921 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006922 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006923 cfgerr++;
6924 }
6925 else if (target->table.size == 0) {
6926 Alert("Proxy '%s': table '%s' used but not configured.\n",
6927 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6928 cfgerr++;
6929 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006930 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6931 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6932 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 +01006933 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006934 cfgerr++;
6935 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006936 else {
6937 free(trule->act_prm.trk_ctr.table.n);
6938 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006939 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006940 * to pass a list of counters to track and allocate them right here using
6941 * stktable_alloc_data_type().
6942 */
6943 }
6944 }
6945
Willy Tarreaud1f96522010-08-03 19:34:32 +02006946 /* find the target table for 'tcp-request' layer 6 rules */
6947 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6948 struct proxy *target;
6949
Willy Tarreaub4c84932013-07-23 19:15:30 +02006950 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006951 continue;
6952
6953 if (trule->act_prm.trk_ctr.table.n)
6954 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6955 else
6956 target = curproxy;
6957
6958 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006959 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6960 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006961 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006962 cfgerr++;
6963 }
6964 else if (target->table.size == 0) {
6965 Alert("Proxy '%s': table '%s' used but not configured.\n",
6966 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6967 cfgerr++;
6968 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006969 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6970 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6971 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 +01006972 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006973 cfgerr++;
6974 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006975 else {
6976 free(trule->act_prm.trk_ctr.table.n);
6977 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006978 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006979 * to pass a list of counters to track and allocate them right here using
6980 * stktable_alloc_data_type().
6981 */
6982 }
6983 }
6984
Emeric Brun32da3c42010-09-23 18:39:19 +02006985 if (curproxy->table.peers.name) {
6986 struct peers *curpeers = peers;
6987
6988 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6989 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6990 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006991 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006992 break;
6993 }
6994 }
6995
6996 if (!curpeers) {
6997 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6998 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006999 free((void *)curproxy->table.peers.name);
7000 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007001 cfgerr++;
7002 }
7003 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007004 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7005 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007006 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007007 cfgerr++;
7008 }
7009 }
7010
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007011 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007012 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007013 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7014 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7015 "proxy", curproxy->id);
7016 cfgerr++;
7017 goto out_uri_auth_compat;
7018 }
7019
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007020 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007021 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007022 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007023 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007024
Willy Tarreau95fa4692010-02-01 13:05:50 +01007025 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7026 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007027
7028 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007029 uri_auth_compat_req[i++] = "realm";
7030 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7031 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007032
Willy Tarreau95fa4692010-02-01 13:05:50 +01007033 uri_auth_compat_req[i++] = "unless";
7034 uri_auth_compat_req[i++] = "{";
7035 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7036 uri_auth_compat_req[i++] = "}";
7037 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007038
Willy Tarreauff011f22011-01-06 17:51:27 +01007039 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7040 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007041 cfgerr++;
7042 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007043 }
7044
Willy Tarreauff011f22011-01-06 17:51:27 +01007045 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007046
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007047 if (curproxy->uri_auth->auth_realm) {
7048 free(curproxy->uri_auth->auth_realm);
7049 curproxy->uri_auth->auth_realm = NULL;
7050 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007051
7052 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007053 }
7054out_uri_auth_compat:
7055
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007056 /* compile the log format */
7057 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007058 if (curproxy->conf.logformat_string != default_http_log_format &&
7059 curproxy->conf.logformat_string != default_tcp_log_format &&
7060 curproxy->conf.logformat_string != clf_http_log_format)
7061 free(curproxy->conf.logformat_string);
7062 curproxy->conf.logformat_string = NULL;
7063 free(curproxy->conf.lfs_file);
7064 curproxy->conf.lfs_file = NULL;
7065 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007066 }
7067
Willy Tarreau62a61232013-04-12 18:13:46 +02007068 if (curproxy->conf.logformat_string) {
7069 curproxy->conf.args.ctx = ARGC_LOG;
7070 curproxy->conf.args.file = curproxy->conf.lfs_file;
7071 curproxy->conf.args.line = curproxy->conf.lfs_line;
7072 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007073 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02007074 curproxy->conf.args.file = NULL;
7075 curproxy->conf.args.line = 0;
7076 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007077
Willy Tarreau62a61232013-04-12 18:13:46 +02007078 if (curproxy->conf.uniqueid_format_string) {
7079 curproxy->conf.args.ctx = ARGC_UIF;
7080 curproxy->conf.args.file = curproxy->conf.uif_file;
7081 curproxy->conf.args.line = curproxy->conf.uif_line;
7082 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007083 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02007084 curproxy->conf.args.file = NULL;
7085 curproxy->conf.args.line = 0;
7086 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007087
7088 /* only now we can check if some args remain unresolved */
7089 cfgerr += smp_resolve_args(curproxy);
7090 if (!cfgerr)
7091 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007092
Willy Tarreau2738a142006-07-08 17:28:09 +02007093 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007094 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007095 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007096 (!curproxy->timeout.connect ||
7097 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007098 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007099 " | While not properly invalid, you will certainly encounter various problems\n"
7100 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007101 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007102 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007103 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007104 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007105
Willy Tarreau1fa31262007-12-03 00:36:16 +01007106 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7107 * We must still support older configurations, so let's find out whether those
7108 * parameters have been set or must be copied from contimeouts.
7109 */
7110 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007111 if (!curproxy->timeout.tarpit ||
7112 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007113 /* tarpit timeout not set. We search in the following order:
7114 * default.tarpit, curr.connect, default.connect.
7115 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007116 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007117 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007118 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007119 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007120 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007121 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007122 }
7123 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007124 (!curproxy->timeout.queue ||
7125 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007126 /* queue timeout not set. We search in the following order:
7127 * default.queue, curr.connect, default.connect.
7128 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007129 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007130 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007131 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007132 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007133 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007134 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007135 }
7136 }
7137
Willy Tarreau1620ec32011-08-06 17:05:02 +02007138 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007139 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7140 curproxy->check_req = (char *)malloc(curproxy->check_len);
7141 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007142 }
7143
Willy Tarreau193b8c62012-11-22 00:17:38 +01007144 /* ensure that cookie capture length is not too large */
7145 if (curproxy->capture_len >= global.tune.cookie_len) {
7146 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7147 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7148 err_code |= ERR_WARN;
7149 curproxy->capture_len = global.tune.cookie_len - 1;
7150 }
7151
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007152 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007153 if (curproxy->nb_req_cap) {
7154 if (curproxy->mode == PR_MODE_HTTP) {
7155 curproxy->req_cap_pool = create_pool("ptrcap",
7156 curproxy->nb_req_cap * sizeof(char *),
7157 MEM_F_SHARED);
7158 } else {
7159 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7160 proxy_type_str(curproxy), curproxy->id);
7161 err_code |= ERR_WARN;
7162 curproxy->to_log &= ~LW_REQHDR;
7163 curproxy->nb_req_cap = 0;
7164 }
7165 }
7166
7167 if (curproxy->nb_rsp_cap) {
7168 if (curproxy->mode == PR_MODE_HTTP) {
7169 curproxy->rsp_cap_pool = create_pool("ptrcap",
7170 curproxy->nb_rsp_cap * sizeof(char *),
7171 MEM_F_SHARED);
7172 } else {
7173 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7174 proxy_type_str(curproxy), curproxy->id);
7175 err_code |= ERR_WARN;
7176 curproxy->to_log &= ~LW_REQHDR;
7177 curproxy->nb_rsp_cap = 0;
7178 }
7179 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007180
Willy Tarreaubaaee002006-06-26 02:48:02 +02007181 /* first, we will invert the servers list order */
7182 newsrv = NULL;
7183 while (curproxy->srv) {
7184 struct server *next;
7185
7186 next = curproxy->srv->next;
7187 curproxy->srv->next = newsrv;
7188 newsrv = curproxy->srv;
7189 if (!next)
7190 break;
7191 curproxy->srv = next;
7192 }
7193
Willy Tarreau17edc812014-01-03 12:14:34 +01007194 /* Check that no server name conflicts. This causes trouble in the stats.
7195 * We only emit a warning for the first conflict affecting each server,
7196 * in order to avoid combinatory explosion if all servers have the same
7197 * name. We do that only for servers which do not have an explicit ID,
7198 * because these IDs were made also for distinguishing them and we don't
7199 * want to annoy people who correctly manage them.
7200 */
7201 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7202 struct server *other_srv;
7203
7204 if (newsrv->puid)
7205 continue;
7206
7207 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7208 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7209 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7210 newsrv->conf.file, newsrv->conf.line,
7211 proxy_type_str(curproxy), curproxy->id,
7212 newsrv->id, other_srv->conf.line);
7213 break;
7214 }
7215 }
7216 }
7217
Willy Tarreaudd701652010-05-25 23:03:02 +02007218 /* assign automatic UIDs to servers which don't have one yet */
7219 next_id = 1;
7220 newsrv = curproxy->srv;
7221 while (newsrv != NULL) {
7222 if (!newsrv->puid) {
7223 /* server ID not set, use automatic numbering with first
7224 * spare entry starting with next_svid.
7225 */
7226 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7227 newsrv->conf.id.key = newsrv->puid = next_id;
7228 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7229 }
7230 next_id++;
7231 newsrv = newsrv->next;
7232 }
7233
Willy Tarreau20697042007-11-15 23:26:18 +01007234 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007235 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007236
Willy Tarreau62c3be22012-01-20 13:12:32 +01007237 /*
7238 * If this server supports a maxconn parameter, it needs a dedicated
7239 * tasks to fill the emptied slots when a connection leaves.
7240 * Also, resolve deferred tracking dependency if needed.
7241 */
7242 newsrv = curproxy->srv;
7243 while (newsrv != NULL) {
7244 if (newsrv->minconn > newsrv->maxconn) {
7245 /* Only 'minconn' was specified, or it was higher than or equal
7246 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7247 * this will avoid further useless expensive computations.
7248 */
7249 newsrv->maxconn = newsrv->minconn;
7250 } else if (newsrv->maxconn && !newsrv->minconn) {
7251 /* minconn was not specified, so we set it to maxconn */
7252 newsrv->minconn = newsrv->maxconn;
7253 }
7254
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007255#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007256 if (newsrv->use_ssl || newsrv->check.use_ssl)
7257 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007258#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007259
Willy Tarreau2f075e92013-12-03 11:11:34 +01007260 /* set the check type on the server */
7261 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7262
Willy Tarreau62c3be22012-01-20 13:12:32 +01007263 if (newsrv->trackit) {
7264 struct proxy *px;
7265 struct server *srv;
7266 char *pname, *sname;
7267
7268 pname = newsrv->trackit;
7269 sname = strrchr(pname, '/');
7270
7271 if (sname)
7272 *sname++ = '\0';
7273 else {
7274 sname = pname;
7275 pname = NULL;
7276 }
7277
7278 if (pname) {
7279 px = findproxy(pname, PR_CAP_BE);
7280 if (!px) {
7281 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7282 proxy_type_str(curproxy), curproxy->id,
7283 newsrv->id, pname);
7284 cfgerr++;
7285 goto next_srv;
7286 }
7287 } else
7288 px = curproxy;
7289
7290 srv = findserver(px, sname);
7291 if (!srv) {
7292 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7293 proxy_type_str(curproxy), curproxy->id,
7294 newsrv->id, sname);
7295 cfgerr++;
7296 goto next_srv;
7297 }
7298
Willy Tarreauff5ae352013-12-11 20:36:34 +01007299 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007300 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7301 "tracking as it does not have checks enabled.\n",
7302 proxy_type_str(curproxy), curproxy->id,
7303 newsrv->id, px->id, srv->id);
7304 cfgerr++;
7305 goto next_srv;
7306 }
7307
7308 if (curproxy != px &&
7309 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7310 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7311 "tracking: disable-on-404 option inconsistency.\n",
7312 proxy_type_str(curproxy), curproxy->id,
7313 newsrv->id, px->id, srv->id);
7314 cfgerr++;
7315 goto next_srv;
7316 }
7317
7318 /* if the other server is forced disabled, we have to do the same here */
7319 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007320 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007321 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007322 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007323 }
7324
7325 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007326 newsrv->tracknext = srv->trackers;
7327 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007328
7329 free(newsrv->trackit);
7330 newsrv->trackit = NULL;
7331 }
7332 next_srv:
7333 newsrv = newsrv->next;
7334 }
7335
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007336 /* We have to initialize the server lookup mechanism depending
7337 * on what LB algorithm was choosen.
7338 */
7339
7340 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7341 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7342 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007343 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7344 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7345 init_server_map(curproxy);
7346 } else {
7347 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7348 fwrr_init_server_groups(curproxy);
7349 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007350 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007351
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007352 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007353 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7354 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7355 fwlc_init_server_tree(curproxy);
7356 } else {
7357 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7358 fas_init_server_tree(curproxy);
7359 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007360 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007361
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007362 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007363 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7364 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7365 chash_init_server_tree(curproxy);
7366 } else {
7367 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7368 init_server_map(curproxy);
7369 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007370 break;
7371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007372
7373 if (curproxy->options & PR_O_LOGASAP)
7374 curproxy->to_log &= ~LW_BYTES;
7375
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007376 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007377 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007378 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7379 proxy_type_str(curproxy), curproxy->id);
7380 err_code |= ERR_WARN;
7381 }
7382
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007383 if (curproxy->mode != PR_MODE_HTTP) {
7384 int optnum;
7385
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007386 if (curproxy->uri_auth) {
7387 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7388 proxy_type_str(curproxy), curproxy->id);
7389 err_code |= ERR_WARN;
7390 curproxy->uri_auth = NULL;
7391 }
7392
Willy Tarreau87cf5142011-08-19 22:57:24 +02007393 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007394 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7395 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7396 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007397 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007398 }
7399
7400 if (curproxy->options & PR_O_ORGTO) {
7401 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7402 "originalto", proxy_type_str(curproxy), curproxy->id);
7403 err_code |= ERR_WARN;
7404 curproxy->options &= ~PR_O_ORGTO;
7405 }
7406
7407 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7408 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7409 (curproxy->cap & cfg_opts[optnum].cap) &&
7410 (curproxy->options & cfg_opts[optnum].val)) {
7411 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7412 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7413 err_code |= ERR_WARN;
7414 curproxy->options &= ~cfg_opts[optnum].val;
7415 }
7416 }
7417
7418 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7419 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7420 (curproxy->cap & cfg_opts2[optnum].cap) &&
7421 (curproxy->options2 & cfg_opts2[optnum].val)) {
7422 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7423 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7424 err_code |= ERR_WARN;
7425 curproxy->options2 &= ~cfg_opts2[optnum].val;
7426 }
7427 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007428
Pieter Baauwd551fb52013-05-08 22:49:23 +02007429#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007430 if (curproxy->conn_src.bind_hdr_occ) {
7431 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007432 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007433 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007434 err_code |= ERR_WARN;
7435 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007436#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007437 }
7438
Willy Tarreaubaaee002006-06-26 02:48:02 +02007439 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007440 * ensure that we're not cross-dressing a TCP server into HTTP.
7441 */
7442 newsrv = curproxy->srv;
7443 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007444 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007445 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7446 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007447 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007448 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007449
Willy Tarreau0cec3312011-10-31 13:49:26 +01007450 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7451 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7452 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7453 err_code |= ERR_WARN;
7454 }
7455
Willy Tarreau82ffa392013-08-13 17:19:08 +02007456 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7457 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7458 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7459 err_code |= ERR_WARN;
7460 }
7461
Pieter Baauwd551fb52013-05-08 22:49:23 +02007462#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007463 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7464 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007465 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 +01007466 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007467 err_code |= ERR_WARN;
7468 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007469#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007470 newsrv = newsrv->next;
7471 }
7472
Willy Tarreauc1a21672009-08-16 22:37:44 +02007473 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007474 if (!curproxy->accept)
7475 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007476
Willy Tarreauc1a21672009-08-16 22:37:44 +02007477 if (curproxy->tcp_req.inspect_delay ||
7478 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007479 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007480
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007481 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007482 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007483 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007484 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007485
7486 /* both TCP and HTTP must check switching rules */
7487 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7488 }
7489
7490 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007491 if (curproxy->tcp_req.inspect_delay ||
7492 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7493 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7494
Emeric Brun97679e72010-09-23 17:56:44 +02007495 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7496 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7497
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007498 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007499 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007500 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007501 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007502
7503 /* If the backend does requires RDP cookie persistence, we have to
7504 * enable the corresponding analyser.
7505 */
7506 if (curproxy->options2 & PR_O2_RDPC_PRST)
7507 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7508 }
7509
Emeric Brunc52962f2012-11-15 18:28:02 +01007510#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007511 /* Configure SSL for each bind line.
7512 * Note: if configuration fails at some point, the ->ctx member
7513 * remains NULL so that listeners can later detach.
7514 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007515 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007516 if (!bind_conf->is_ssl) {
7517 if (bind_conf->default_ctx) {
7518 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7519 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7520 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007521 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007522 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007523 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007524 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007525 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007526 cfgerr++;
7527 continue;
7528 }
7529
Emeric Brun4b3091e2012-09-24 15:48:52 +02007530 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007531 Alert("Unable to allocate SSL session cache.\n");
7532 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007533 continue;
7534 }
7535
Emeric Brunfc0421f2012-09-07 17:30:07 +02007536 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007537 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007538 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007539#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007540
Willy Tarreaue6b98942007-10-29 01:09:36 +01007541 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007542 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007543 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007544 if (!listener->luid) {
7545 /* listener ID not set, use automatic numbering with first
7546 * spare entry starting with next_luid.
7547 */
7548 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7549 listener->conf.id.key = listener->luid = next_id;
7550 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007551 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007552 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007553
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007554 /* enable separate counters */
7555 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7556 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007557 if (!listener->name)
7558 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007559 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007560
Willy Tarreaue6b98942007-10-29 01:09:36 +01007561 if (curproxy->options & PR_O_TCP_NOLING)
7562 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007563 if (!listener->maxconn)
7564 listener->maxconn = curproxy->maxconn;
7565 if (!listener->backlog)
7566 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007567 if (!listener->maxaccept)
7568 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7569
7570 /* we want to have an optimal behaviour on single process mode to
7571 * maximize the work at once, but in multi-process we want to keep
7572 * some fairness between processes, so we target half of the max
7573 * number of events to be balanced over all the processes the proxy
7574 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7575 * used to disable the limit.
7576 */
7577 if (listener->maxaccept > 0) {
7578 if (nbproc > 1)
7579 listener->maxaccept = (listener->maxaccept + 1) / 2;
7580 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7581 }
7582
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007583 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007584 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007585 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007586 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007587
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007588 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7589 listener->options |= LI_O_TCP_RULES;
7590
Willy Tarreaude3041d2010-05-31 10:56:17 +02007591 if (curproxy->mon_mask.s_addr)
7592 listener->options |= LI_O_CHK_MONNET;
7593
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007594 /* smart accept mode is automatic in HTTP mode */
7595 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007596 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007597 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7598 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007599 }
7600
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007601 /* Release unused SSL configs */
7602 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7603 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007604 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007605#ifdef USE_OPENSSL
7606 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007607 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007608 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007609 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007610 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007611#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007612 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007613
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007614 /* Check multi-process mode compatibility for the current proxy */
7615 if (global.nbproc > 1) {
7616 int nbproc = 0;
7617 if (curproxy->bind_proc) {
7618 int proc;
7619 for (proc = 0; proc < global.nbproc; proc++) {
7620 if (curproxy->bind_proc & (1 << proc)) {
7621 nbproc++;
7622 }
7623 }
7624 } else {
7625 nbproc = global.nbproc;
7626 }
7627 if (curproxy->table.peers.name) {
7628 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7629 curproxy->id);
7630 cfgerr++;
7631 }
7632 if (nbproc > 1) {
7633 if (curproxy->uri_auth) {
7634 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7635 curproxy->id);
7636 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7637 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7638 curproxy->id);
7639 }
7640 }
7641 if (curproxy->appsession_name) {
7642 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7643 curproxy->id);
7644 }
7645 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7646 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7647 curproxy->id);
7648 }
7649 }
7650 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007651
7652 /* create the task associated with the proxy */
7653 curproxy->task = task_new();
7654 if (curproxy->task) {
7655 curproxy->task->context = curproxy;
7656 curproxy->task->process = manage_proxy;
7657 /* no need to queue, it will be done automatically if some
7658 * listener gets limited.
7659 */
7660 curproxy->task->expire = TICK_ETERNITY;
7661 } else {
7662 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7663 curproxy->id);
7664 cfgerr++;
7665 }
7666
Willy Tarreaubaaee002006-06-26 02:48:02 +02007667 curproxy = curproxy->next;
7668 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007669
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007670 /* Check multi-process mode compatibility */
7671 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007672 if (global.stats_fe && !global.stats_fe->bind_proc) {
7673 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 +01007674 }
7675 }
7676
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007677 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7678 struct auth_users *curuser;
7679 int g;
7680
7681 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7682 unsigned int group_mask = 0;
7683 char *group = NULL;
7684
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007685 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007686 continue;
7687
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007688 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007689
7690 for (g = 0; g < curuserlist->grpcnt; g++)
7691 if (!strcmp(curuserlist->groups[g], group))
7692 break;
7693
7694 if (g == curuserlist->grpcnt) {
7695 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7696 curuserlist->name, group, curuser->user);
7697 err_code |= ERR_ALERT | ERR_FATAL;
7698 goto out;
7699 }
7700
7701 group_mask |= (1 << g);
7702 }
7703
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007704 free(curuser->u.groups);
7705 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007706 }
7707
7708 for (g = 0; g < curuserlist->grpcnt; g++) {
7709 char *user = NULL;
7710
7711 if (!curuserlist->groupusers[g])
7712 continue;
7713
7714 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7715 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7716 if (!strcmp(curuser->user, user))
7717 break;
7718
7719 if (!curuser) {
7720 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7721 curuserlist->name, user, curuserlist->groups[g]);
7722 err_code |= ERR_ALERT | ERR_FATAL;
7723 goto out;
7724 }
7725
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007726 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007727 }
7728
7729 free(curuserlist->groupusers[g]);
7730 }
7731
7732 free(curuserlist->groupusers);
7733
7734#ifdef DEBUG_AUTH
7735 for (g = 0; g < curuserlist->grpcnt; g++) {
7736 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7737
7738 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007739 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007740 fprintf(stderr, " %s", curuser->user);
7741 }
7742
7743 fprintf(stderr, "\n");
7744 }
7745#endif
7746
Willy Tarreaufbb78422011-06-05 15:38:35 +02007747 }
7748
7749 /* automatically compute fullconn if not set. We must not do it in the
7750 * loop above because cross-references are not yet fully resolved.
7751 */
7752 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7753 /* If <fullconn> is not set, let's set it to 10% of the sum of
7754 * the possible incoming frontend's maxconns.
7755 */
7756 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7757 struct proxy *fe;
7758 int total = 0;
7759
7760 /* sum up the number of maxconns of frontends which
7761 * reference this backend at least once or which are
7762 * the same one ('listen').
7763 */
7764 for (fe = proxy; fe; fe = fe->next) {
7765 struct switching_rule *rule;
7766 struct hdr_exp *exp;
7767 int found = 0;
7768
7769 if (!(fe->cap & PR_CAP_FE))
7770 continue;
7771
7772 if (fe == curproxy) /* we're on a "listen" instance */
7773 found = 1;
7774
7775 if (fe->defbe.be == curproxy) /* "default_backend" */
7776 found = 1;
7777
7778 /* check if a "use_backend" rule matches */
7779 if (!found) {
7780 list_for_each_entry(rule, &fe->switching_rules, list) {
7781 if (rule->be.backend == curproxy) {
7782 found = 1;
7783 break;
7784 }
7785 }
7786 }
7787
7788 /* check if a "reqsetbe" rule matches */
7789 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7790 if (exp->action == ACT_SETBE &&
7791 (struct proxy *)exp->replace == curproxy) {
7792 found = 1;
7793 break;
7794 }
7795 }
7796
7797 /* now we've checked all possible ways to reference a backend
7798 * from a frontend.
7799 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007800 if (!found)
7801 continue;
7802 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007803 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007804 /* we have the sum of the maxconns in <total>. We only
7805 * keep 10% of that sum to set the default fullconn, with
7806 * a hard minimum of 1 (to avoid a divide by zero).
7807 */
7808 curproxy->fullconn = (total + 9) / 10;
7809 if (!curproxy->fullconn)
7810 curproxy->fullconn = 1;
7811 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007812 }
7813
Willy Tarreau056f5682010-06-06 15:51:11 +02007814 /* initialize stick-tables on backend capable proxies. This must not
7815 * be done earlier because the data size may be discovered while parsing
7816 * other proxies.
7817 */
Godbach9703e662013-12-11 21:11:41 +08007818 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007819 if (curproxy->state == PR_STSTOPPED)
7820 continue;
7821
Godbach9703e662013-12-11 21:11:41 +08007822 if (!stktable_init(&curproxy->table)) {
7823 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7824 cfgerr++;
7825 }
7826 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007827
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007828 /*
7829 * Recount currently required checks.
7830 */
7831
7832 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7833 int optnum;
7834
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007835 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7836 if (curproxy->options & cfg_opts[optnum].val)
7837 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007838
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007839 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7840 if (curproxy->options2 & cfg_opts2[optnum].val)
7841 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007842 }
7843
Willy Tarreau122541c2011-09-07 21:24:49 +02007844 if (peers) {
7845 struct peers *curpeers = peers, **last;
7846 struct peer *p, *pb;
7847
7848 /* Remove all peers sections which don't have a valid listener.
7849 * This can happen when a peers section is never referenced and
7850 * does not contain a local peer.
7851 */
7852 last = &peers;
7853 while (*last) {
7854 curpeers = *last;
7855 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007856 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007857 last = &curpeers->next;
7858 continue;
7859 }
7860
7861 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7862 curpeers->id, localpeer);
7863
7864 p = curpeers->remote;
7865 while (p) {
7866 pb = p->next;
7867 free(p->id);
7868 free(p);
7869 p = pb;
7870 }
7871
7872 /* Destroy and unlink this curpeers section.
7873 * Note: curpeers is backed up into *last.
7874 */
7875 free(curpeers->id);
7876 curpeers = curpeers->next;
7877 free(*last);
7878 *last = curpeers;
7879 }
7880 }
7881
Willy Tarreau34eb6712011-10-24 18:15:04 +02007882 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007883 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007884 MEM_F_SHARED);
7885
Willy Tarreaubb925012009-07-23 13:36:36 +02007886 if (cfgerr > 0)
7887 err_code |= ERR_ALERT | ERR_FATAL;
7888 out:
7889 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007890}
7891
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007892/*
7893 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7894 * parsing sessions.
7895 */
7896void cfg_register_keywords(struct cfg_kw_list *kwl)
7897{
7898 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7899}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007900
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007901/*
7902 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7903 */
7904void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7905{
7906 LIST_DEL(&kwl->list);
7907 LIST_INIT(&kwl->list);
7908}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007909
7910/*
7911 * Local variables:
7912 * c-indent-level: 8
7913 * c-basic-offset: 8
7914 * End:
7915 */