blob: 5635c5716af3efa25317750e41bc8cc955e1c0b4 [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 Tarreau7cbc9152014-03-15 08:17:08 +01001778 struct ebpt_node *node;
1779
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 if (!*args[1]) {
1781 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1782 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1783 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_ABORT;
1785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001787
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001788 err = invalid_char(args[1]);
1789 if (err) {
1790 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1791 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001792 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001793 }
1794
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001795 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1796 curproxy = container_of(node, struct proxy, conf.by_name);
1797
1798 if (strcmp(curproxy->id, args[1]) != 0)
1799 break;
1800
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001801 /*
1802 * If there are two proxies with the same name only following
1803 * combinations are allowed:
1804 *
1805 * listen backend frontend ruleset
1806 * listen - - - -
1807 * backend - - OK -
1808 * frontend - OK - -
1809 * ruleset - - - -
1810 */
1811
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001812 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1813 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001814 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1815 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1816 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001818 }
1819 }
1820
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1822 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001823 err_code |= ERR_ALERT | ERR_ABORT;
1824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001826
Willy Tarreau97cb7802010-01-03 20:23:58 +01001827 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 curproxy->next = proxy;
1829 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001830 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1831 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001832 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001835 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836
1837 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001838 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001839 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001840
Willy Tarreau4348fad2012-09-20 16:48:07 +02001841 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1842
Willy Tarreau902636f2013-03-10 19:44:48 +01001843 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1844 if (errmsg && *errmsg) {
1845 indent_msg(&errmsg, 2);
1846 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001847 }
1848 else
1849 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1850 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_FATAL;
1852 goto out;
1853 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001854
Willy Tarreau4348fad2012-09-20 16:48:07 +02001855 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001856 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 }
1859
1860 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001861 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001862 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001863
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001866 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001867 curproxy->no_options = defproxy.no_options;
1868 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001869 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001870 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001871 curproxy->except_net = defproxy.except_net;
1872 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001873 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001874 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001876 if (defproxy.fwdfor_hdr_len) {
1877 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1878 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1879 }
1880
Willy Tarreaub86db342009-11-30 11:50:16 +01001881 if (defproxy.orgto_hdr_len) {
1882 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1883 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1884 }
1885
Mark Lamourinec2247f02012-01-04 13:02:01 -05001886 if (defproxy.server_id_hdr_len) {
1887 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1888 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1889 }
1890
Willy Tarreau977b8e42006-12-29 14:19:17 +01001891 if (curproxy->cap & PR_CAP_FE) {
1892 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001893 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001894 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001895
1896 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001897 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1898 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899
1900 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (curproxy->cap & PR_CAP_BE) {
1904 curproxy->fullconn = defproxy.fullconn;
1905 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001907 if (defproxy.check_req) {
1908 curproxy->check_req = calloc(1, defproxy.check_len);
1909 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1910 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001913 if (defproxy.expect_str) {
1914 curproxy->expect_str = strdup(defproxy.expect_str);
1915 if (defproxy.expect_regex) {
1916 /* note: this regex is known to be valid */
1917 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1918 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1919 }
1920 }
1921
Willy Tarreau67402132012-05-31 20:40:20 +02001922 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923 if (defproxy.cookie_name)
1924 curproxy->cookie_name = strdup(defproxy.cookie_name);
1925 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001926 if (defproxy.cookie_domain)
1927 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001928
Willy Tarreau31936852010-10-06 16:59:56 +02001929 if (defproxy.cookie_maxidle)
1930 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1931
1932 if (defproxy.cookie_maxlife)
1933 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1934
Emeric Brun647caf12009-06-30 17:57:00 +02001935 if (defproxy.rdp_cookie_name)
1936 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1937 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1938
Willy Tarreau01732802007-11-01 22:48:15 +01001939 if (defproxy.url_param_name)
1940 curproxy->url_param_name = strdup(defproxy.url_param_name);
1941 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001942
Benoitaffb4812009-03-25 13:02:10 +01001943 if (defproxy.hh_name)
1944 curproxy->hh_name = strdup(defproxy.hh_name);
1945 curproxy->hh_len = defproxy.hh_len;
1946 curproxy->hh_match_domain = defproxy.hh_match_domain;
1947
Willy Tarreauef9a3602012-12-08 22:29:20 +01001948 if (defproxy.conn_src.iface_name)
1949 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1950 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001951 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001952#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001953 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001954#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001957 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 if (defproxy.capture_name)
1959 curproxy->capture_name = strdup(defproxy.capture_name);
1960 curproxy->capture_namelen = defproxy.capture_namelen;
1961 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963
Willy Tarreau977b8e42006-12-29 14:19:17 +01001964 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001965 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001966 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001967 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001968 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969 curproxy->uri_auth = defproxy.uri_auth;
1970 curproxy->mon_net = defproxy.mon_net;
1971 curproxy->mon_mask = defproxy.mon_mask;
1972 if (defproxy.monitor_uri)
1973 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1974 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001975 if (defproxy.defbe.name)
1976 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001977
1978 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001979 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1980 if (curproxy->conf.logformat_string &&
1981 curproxy->conf.logformat_string != default_http_log_format &&
1982 curproxy->conf.logformat_string != default_tcp_log_format &&
1983 curproxy->conf.logformat_string != clf_http_log_format)
1984 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1985
1986 if (defproxy.conf.lfs_file) {
1987 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1988 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1989 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001990 }
1991
1992 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001993 curproxy->timeout.connect = defproxy.timeout.connect;
1994 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001995 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001996 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001997 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001998 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001999 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002000 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002001 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 }
2003
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02002005
2006 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002007 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002008 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002009 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002010 LIST_INIT(&node->list);
2011 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2012 }
2013
Willy Tarreau62a61232013-04-12 18:13:46 +02002014 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2015 if (curproxy->conf.uniqueid_format_string)
2016 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2017
2018 if (defproxy.conf.uif_file) {
2019 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2020 curproxy->conf.uif_line = defproxy.conf.uif_line;
2021 }
William Lallemanda73203e2012-03-12 12:48:57 +01002022
2023 /* copy default header unique id */
2024 if (defproxy.header_unique_id)
2025 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2026
William Lallemand82fe75c2012-10-23 10:25:10 +02002027 /* default compression options */
2028 if (defproxy.comp != NULL) {
2029 curproxy->comp = calloc(1, sizeof(struct comp));
2030 curproxy->comp->algos = defproxy.comp->algos;
2031 curproxy->comp->types = defproxy.comp->types;
2032 }
2033
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002035 curproxy->conf.used_listener_id = EB_ROOT;
2036 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002037
Willy Tarreau93893792009-07-23 13:19:11 +02002038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 }
2040 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2041 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002042 /* FIXME-20070101: we should do this too at the end of the
2043 * config parsing to free all default values.
2044 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002045 free(defproxy.check_req);
2046 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002047 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002048 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002049 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002050 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002051 free(defproxy.capture_name);
2052 free(defproxy.monitor_uri);
2053 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002054 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002055 free(defproxy.fwdfor_hdr_name);
2056 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002057 free(defproxy.orgto_hdr_name);
2058 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002059 free(defproxy.server_id_hdr_name);
2060 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002061 free(defproxy.expect_str);
2062 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002063
Willy Tarreau62a61232013-04-12 18:13:46 +02002064 if (defproxy.conf.logformat_string != default_http_log_format &&
2065 defproxy.conf.logformat_string != default_tcp_log_format &&
2066 defproxy.conf.logformat_string != clf_http_log_format)
2067 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002068
Willy Tarreau62a61232013-04-12 18:13:46 +02002069 free(defproxy.conf.uniqueid_format_string);
2070 free(defproxy.conf.lfs_file);
2071 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002072
Willy Tarreaua534fea2008-08-03 12:19:50 +02002073 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002074 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002075
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 /* we cannot free uri_auth because it might already be used */
2077 init_default_instance();
2078 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002079 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2080 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 }
2084 else if (curproxy == NULL) {
2085 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002089
2090 /* update the current file and line being parsed */
2091 curproxy->conf.args.file = curproxy->conf.file;
2092 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002093
2094 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002096 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002097 int cur_arg;
2098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (curproxy == &defproxy) {
2100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002101 err_code |= ERR_ALERT | ERR_FATAL;
2102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106
Willy Tarreau24709282013-03-10 21:32:12 +01002107 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002108 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002113
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002114 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002115
2116 /* use default settings for unix sockets */
2117 bind_conf->ux.uid = global.unix_bind.ux.uid;
2118 bind_conf->ux.gid = global.unix_bind.ux.gid;
2119 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002120
2121 /* NOTE: the following line might create several listeners if there
2122 * are comma-separated IPs or port ranges. So all further processing
2123 * will have to be applied to all listeners created after last_listen.
2124 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002125 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2126 if (errmsg && *errmsg) {
2127 indent_msg(&errmsg, 2);
2128 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002129 }
2130 else
2131 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2132 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
2135 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002136
Willy Tarreau4348fad2012-09-20 16:48:07 +02002137 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2138 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002139 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002140 }
2141
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002142 cur_arg = 2;
2143 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002144 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002145 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002146 char *err;
2147
Willy Tarreau26982662012-09-12 23:17:10 +02002148 kw = bind_find_kw(args[cur_arg]);
2149 if (kw) {
2150 char *err = NULL;
2151 int code;
2152
2153 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002154 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2155 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002156 cur_arg += 1 + kw->skip ;
2157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
2159 }
2160
Willy Tarreau4348fad2012-09-20 16:48:07 +02002161 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002162 err_code |= code;
2163
2164 if (code) {
2165 if (err && *err) {
2166 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002167 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002168 }
2169 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002170 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2171 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002172 if (code & ERR_FATAL) {
2173 free(err);
2174 cur_arg += 1 + kw->skip;
2175 goto out;
2176 }
2177 }
2178 free(err);
2179 cur_arg += 1 + kw->skip;
2180 continue;
2181 }
2182
Willy Tarreau8638f482012-09-18 18:01:17 +02002183 err = NULL;
2184 if (!bind_dumped) {
2185 bind_dump_kws(&err);
2186 indent_msg(&err, 4);
2187 bind_dumped = 1;
2188 }
2189
2190 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2191 file, linenum, args[0], args[1], args[cur_arg],
2192 err ? " Registered keywords :" : "", err ? err : "");
2193 free(err);
2194
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002197 }
Willy Tarreau93893792009-07-23 13:19:11 +02002198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 }
2200 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002201 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002202 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002207 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 /* flush useless bits */
2211 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002214 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217
Willy Tarreau1c47f852006-07-09 08:22:27 +02002218 if (!*args[1]) {
2219 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002223 }
2224
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002226 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002227 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002228 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002229 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2230
Willy Tarreau93893792009-07-23 13:19:11 +02002231 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2234 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2235 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2236 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2237 else {
2238 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 }
2242 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002243 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002244 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002245
2246 if (curproxy == &defproxy) {
2247 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002251 }
2252
2253 if (!*args[1]) {
2254 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2255 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002258 }
2259
2260 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002261 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002262
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002263 if (curproxy->uuid <= 0) {
2264 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002265 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002268 }
2269
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002270 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2271 if (node) {
2272 struct proxy *target = container_of(node, struct proxy, conf.id);
2273 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2274 file, linenum, proxy_type_str(curproxy), curproxy->id,
2275 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2276 err_code |= ERR_ALERT | ERR_FATAL;
2277 goto out;
2278 }
2279 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002280 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002281 else if (!strcmp(args[0], "description")) {
2282 int i, len=0;
2283 char *d;
2284
Cyril Bonté99ed3272010-01-24 23:29:44 +01002285 if (curproxy == &defproxy) {
2286 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2287 file, linenum, args[0]);
2288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002292 if (!*args[1]) {
2293 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2294 file, linenum, args[0]);
2295 return -1;
2296 }
2297
2298 for(i=1; *args[i]; i++)
2299 len += strlen(args[i])+1;
2300
2301 d = (char *)calloc(1, len);
2302 curproxy->desc = d;
2303
2304 d += sprintf(d, "%s", args[1]);
2305 for(i=2; *args[i]; i++)
2306 d += sprintf(d, " %s", args[i]);
2307
2308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2310 curproxy->state = PR_STSTOPPED;
2311 }
2312 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2313 curproxy->state = PR_STNEW;
2314 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002315 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2316 int cur_arg = 1;
2317 unsigned int set = 0;
2318
2319 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002320 unsigned int low, high;
2321
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002322 if (strcmp(args[cur_arg], "all") == 0) {
2323 set = 0;
2324 break;
2325 }
2326 else if (strcmp(args[cur_arg], "odd") == 0) {
2327 set |= 0x55555555;
2328 }
2329 else if (strcmp(args[cur_arg], "even") == 0) {
2330 set |= 0xAAAAAAAA;
2331 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002332 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002333 char *dash = strchr(args[cur_arg], '-');
2334
2335 low = high = str2uic(args[cur_arg]);
2336 if (dash)
2337 high = str2uic(dash + 1);
2338
2339 if (high < low) {
2340 unsigned int swap = low;
2341 low = high;
2342 high = swap;
2343 }
2344
2345 if (low < 1 || high > 32) {
2346 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002350 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002351
2352 if (high > global.nbproc) {
2353 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2354 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002356 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002357 while (low <= high)
2358 set |= 1 << (low++ - 1);
2359 }
2360 else {
2361 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2362 file, linenum, args[0]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002365 }
2366 cur_arg++;
2367 }
2368 curproxy->bind_proc = set;
2369 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002370 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002371 if (curproxy == &defproxy) {
2372 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002375 }
2376
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002377 err = invalid_char(args[1]);
2378 if (err) {
2379 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2380 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002382 }
2383
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002384 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002385 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2386 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002389 }
2390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2392 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393
Willy Tarreau977b8e42006-12-29 14:19:17 +01002394 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002396
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 if (*(args[1]) == 0) {
2398 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002403
Willy Tarreau67402132012-05-31 20:40:20 +02002404 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002405 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002406 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002407 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 curproxy->cookie_name = strdup(args[1]);
2409 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002410
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 cur_arg = 2;
2412 while (*(args[cur_arg])) {
2413 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002414 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 }
2416 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002417 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 }
2419 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002420 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002423 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 }
2425 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002426 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002428 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002429 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002432 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002434 else if (!strcmp(args[cur_arg], "httponly")) {
2435 curproxy->ck_opts |= PR_CK_HTTPONLY;
2436 }
2437 else if (!strcmp(args[cur_arg], "secure")) {
2438 curproxy->ck_opts |= PR_CK_SECURE;
2439 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002440 else if (!strcmp(args[cur_arg], "domain")) {
2441 if (!*args[cur_arg + 1]) {
2442 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2443 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002446 }
2447
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002448 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002449 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002450 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2451 " dots nor does not start with a dot."
2452 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002453 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002454 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002455 }
2456
2457 err = invalid_domainchar(args[cur_arg + 1]);
2458 if (err) {
2459 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2460 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002463 }
2464
Willy Tarreau68a897b2009-12-03 23:28:34 +01002465 if (!curproxy->cookie_domain) {
2466 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2467 } else {
2468 /* one domain was already specified, add another one by
2469 * building the string which will be returned along with
2470 * the cookie.
2471 */
2472 char *new_ptr;
2473 int new_len = strlen(curproxy->cookie_domain) +
2474 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2475 new_ptr = malloc(new_len);
2476 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2477 free(curproxy->cookie_domain);
2478 curproxy->cookie_domain = new_ptr;
2479 }
Willy Tarreau31936852010-10-06 16:59:56 +02002480 cur_arg++;
2481 }
2482 else if (!strcmp(args[cur_arg], "maxidle")) {
2483 unsigned int maxidle;
2484 const char *res;
2485
2486 if (!*args[cur_arg + 1]) {
2487 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2488 file, linenum, args[cur_arg]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492
2493 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2494 if (res) {
2495 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2496 file, linenum, *res, args[cur_arg]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500 curproxy->cookie_maxidle = maxidle;
2501 cur_arg++;
2502 }
2503 else if (!strcmp(args[cur_arg], "maxlife")) {
2504 unsigned int maxlife;
2505 const char *res;
2506
2507 if (!*args[cur_arg + 1]) {
2508 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2509 file, linenum, args[cur_arg]);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
2512 }
2513
2514 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2515 if (res) {
2516 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2517 file, linenum, *res, args[cur_arg]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002522 cur_arg++;
2523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002525 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 +02002526 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 }
2530 cur_arg++;
2531 }
Willy Tarreau67402132012-05-31 20:40:20 +02002532 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' 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 }
2537
Willy Tarreau67402132012-05-31 20:40:20 +02002538 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2540 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002543
Willy Tarreau67402132012-05-31 20:40:20 +02002544 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002545 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2546 file, linenum);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002550 else if (!strcmp(args[0], "persist")) { /* persist */
2551 if (*(args[1]) == 0) {
2552 Alert("parsing [%s:%d] : missing persist method.\n",
2553 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002556 }
2557
2558 if (!strncmp(args[1], "rdp-cookie", 10)) {
2559 curproxy->options2 |= PR_O2_RDPC_PRST;
2560
Emeric Brunb982a3d2010-01-04 15:45:53 +01002561 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002562 const char *beg, *end;
2563
2564 beg = args[1] + 11;
2565 end = strchr(beg, ')');
2566
2567 if (!end || end == beg) {
2568 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2569 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002572 }
2573
2574 free(curproxy->rdp_cookie_name);
2575 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2576 curproxy->rdp_cookie_len = end-beg;
2577 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002578 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002579 free(curproxy->rdp_cookie_name);
2580 curproxy->rdp_cookie_name = strdup("msts");
2581 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2582 }
2583 else { /* syntax */
2584 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002588 }
2589 }
2590 else {
2591 Alert("parsing [%s:%d] : unknown persist method.\n",
2592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002595 }
2596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002598 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002600 if (curproxy == &defproxy) {
2601 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
2604 }
2605
Willy Tarreau977b8e42006-12-29 14:19:17 +01002606 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002610 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 }
2615 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002616 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 curproxy->appsession_name = strdup(args[1]);
2618 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2619 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002620 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2621 if (err) {
2622 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2623 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002626 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002627 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002628
Willy Tarreau51041c72007-09-09 21:56:53 +02002629 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2630 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_ABORT;
2632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002634
2635 cur_arg = 6;
2636 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002637 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2638 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002639 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002640 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002641 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002642 } else if (!strcmp(args[cur_arg], "prefix")) {
2643 curproxy->options2 |= PR_O2_AS_PFX;
2644 } else if (!strcmp(args[cur_arg], "mode")) {
2645 if (!*args[cur_arg + 1]) {
2646 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2647 file, linenum, args[0], args[cur_arg]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651
2652 cur_arg++;
2653 if (!strcmp(args[cur_arg], "query-string")) {
2654 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2655 curproxy->options2 |= PR_O2_AS_M_QS;
2656 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2657 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2658 curproxy->options2 |= PR_O2_AS_M_PP;
2659 } else {
2660 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002665 cur_arg++;
2666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 } /* Url App Session */
2668 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002669 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002673 if (curproxy == &defproxy) {
2674 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
2677 }
2678
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 if (*(args[4]) == 0) {
2680 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2681 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002685 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 curproxy->capture_name = strdup(args[2]);
2687 curproxy->capture_namelen = strlen(curproxy->capture_name);
2688 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 curproxy->to_log |= LW_COOKIE;
2690 }
2691 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2692 struct cap_hdr *hdr;
2693
2694 if (curproxy == &defproxy) {
2695 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 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
2699
2700 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2701 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2702 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
2706
2707 hdr = calloc(sizeof(struct cap_hdr), 1);
2708 hdr->next = curproxy->req_cap;
2709 hdr->name = strdup(args[3]);
2710 hdr->namelen = strlen(args[3]);
2711 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002712 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 hdr->index = curproxy->nb_req_cap++;
2714 curproxy->req_cap = hdr;
2715 curproxy->to_log |= LW_REQHDR;
2716 }
2717 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2718 struct cap_hdr *hdr;
2719
2720 if (curproxy == &defproxy) {
2721 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 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 }
2725
2726 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2727 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2728 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 }
2732 hdr = calloc(sizeof(struct cap_hdr), 1);
2733 hdr->next = curproxy->rsp_cap;
2734 hdr->name = strdup(args[3]);
2735 hdr->namelen = strlen(args[3]);
2736 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002737 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 hdr->index = curproxy->nb_rsp_cap++;
2739 curproxy->rsp_cap = hdr;
2740 curproxy->to_log |= LW_RSPHDR;
2741 }
2742 else {
2743 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2744 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 }
2748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 if (*(args[1]) == 0) {
2754 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2755 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 }
2759 curproxy->conn_retries = atol(args[1]);
2760 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002761 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002762 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002763
2764 if (curproxy == &defproxy) {
2765 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
Willy Tarreau20b0de52012-12-24 15:45:22 +01002770 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2771 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2772 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2773 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002774 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002775 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2776 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 +01002777 file, linenum, args[0]);
2778 err_code |= ERR_WARN;
2779 }
2780
Willy Tarreauff011f22011-01-06 17:51:27 +01002781 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002782
Willy Tarreauff011f22011-01-06 17:51:27 +01002783 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002784 err_code |= ERR_ALERT | ERR_ABORT;
2785 goto out;
2786 }
2787
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002788 err_code |= warnif_cond_conflicts(rule->cond,
2789 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2790 file, linenum);
2791
Willy Tarreauff011f22011-01-06 17:51:27 +01002792 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002793 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002794 else if (!strcmp(args[0], "http-response")) { /* response access control */
2795 struct http_res_rule *rule;
2796
2797 if (curproxy == &defproxy) {
2798 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
2803 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2804 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2805 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2806 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2807 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2808 file, linenum, args[0]);
2809 err_code |= ERR_WARN;
2810 }
2811
2812 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2813
2814 if (!rule) {
2815 err_code |= ERR_ALERT | ERR_ABORT;
2816 goto out;
2817 }
2818
2819 err_code |= warnif_cond_conflicts(rule->cond,
2820 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2821 file, linenum);
2822
2823 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2824 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002825 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2826 /* set the header name and length into the proxy structure */
2827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2828 err_code |= ERR_WARN;
2829
2830 if (!*args[1]) {
2831 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2832 file, linenum, args[0]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836
2837 /* set the desired header name */
2838 free(curproxy->server_id_hdr_name);
2839 curproxy->server_id_hdr_name = strdup(args[1]);
2840 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2841 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002842 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002843 if (curproxy == &defproxy) {
2844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002847 }
2848
Willy Tarreauef6494c2010-01-28 17:12:36 +01002849 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002850 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2851 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002854 }
2855
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002856 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2857 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2858 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002861 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002862
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002863 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002864 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002865 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002866 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002867 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002868
Cyril Bonté99ed3272010-01-24 23:29:44 +01002869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002875 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002876 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2877 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002880 }
2881
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002882 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002883 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002884 err_code |= warnif_cond_conflicts(rule->cond,
2885 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2886 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002887 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002888 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002889 struct switching_rule *rule;
2890
Willy Tarreaub099aca2008-10-12 17:26:37 +02002891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002895 }
2896
Willy Tarreau55ea7572007-06-17 19:56:27 +02002897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002899
2900 if (*(args[1]) == 0) {
2901 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002904 }
2905
Willy Tarreauef6494c2010-01-28 17:12:36 +01002906 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002907 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002911 }
2912
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002913 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2914 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2915 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002918 }
2919
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002920 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002921
Willy Tarreau55ea7572007-06-17 19:56:27 +02002922 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2923 rule->cond = cond;
2924 rule->be.name = strdup(args[1]);
2925 LIST_INIT(&rule->list);
2926 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2927 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002928 else if (strcmp(args[0], "use-server") == 0) {
2929 struct server_rule *rule;
2930
2931 if (curproxy == &defproxy) {
2932 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936
2937 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2938 err_code |= ERR_WARN;
2939
2940 if (*(args[1]) == 0) {
2941 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
2946 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2947 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2948 file, linenum, args[0]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002953 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2954 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2955 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002960 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002961
2962 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2963 rule->cond = cond;
2964 rule->srv.name = strdup(args[1]);
2965 LIST_INIT(&rule->list);
2966 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2967 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2968 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002969 else if ((!strcmp(args[0], "force-persist")) ||
2970 (!strcmp(args[0], "ignore-persist"))) {
2971 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002972
2973 if (curproxy == &defproxy) {
2974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
2977 }
2978
2979 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2980 err_code |= ERR_WARN;
2981
Willy Tarreauef6494c2010-01-28 17:12:36 +01002982 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002983 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2984 file, linenum, args[0]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002989 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2990 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2991 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002996 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2997 * where force-persist is applied.
2998 */
2999 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003000
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003001 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003002 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003003 if (!strcmp(args[0], "force-persist")) {
3004 rule->type = PERSIST_TYPE_FORCE;
3005 } else {
3006 rule->type = PERSIST_TYPE_IGNORE;
3007 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003008 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003009 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003010 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003011 else if (!strcmp(args[0], "stick-table")) {
3012 int myidx = 1;
3013
Emeric Brun32da3c42010-09-23 18:39:19 +02003014 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003015 curproxy->table.type = (unsigned int)-1;
3016 while (*args[myidx]) {
3017 const char *err;
3018
3019 if (strcmp(args[myidx], "size") == 0) {
3020 myidx++;
3021 if (!*(args[myidx])) {
3022 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3023 file, linenum, args[myidx-1]);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
3027 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3028 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3029 file, linenum, *err, args[myidx-1]);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003033 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003034 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003035 else if (strcmp(args[myidx], "peers") == 0) {
3036 myidx++;
Godbach50523162013-12-11 19:48:57 +08003037 if (!*(args[myidx])) {
3038 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3039 file, linenum, args[myidx-1]);
3040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
3042 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003043 curproxy->table.peers.name = strdup(args[myidx++]);
3044 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 else if (strcmp(args[myidx], "expire") == 0) {
3046 myidx++;
3047 if (!*(args[myidx])) {
3048 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3049 file, linenum, args[myidx-1]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3054 if (err) {
3055 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3056 file, linenum, *err, args[myidx-1]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
3060 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003061 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 }
3063 else if (strcmp(args[myidx], "nopurge") == 0) {
3064 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003065 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 }
3067 else if (strcmp(args[myidx], "type") == 0) {
3068 myidx++;
3069 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3070 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3071 file, linenum, args[myidx]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003075 /* myidx already points to next arg */
3076 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003077 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003078 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003079 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003080
3081 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003082 nw = args[myidx];
3083 while (*nw) {
3084 /* the "store" keyword supports a comma-separated list */
3085 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003086 sa = NULL; /* store arg */
3087 while (*nw && *nw != ',') {
3088 if (*nw == '(') {
3089 *nw = 0;
3090 sa = ++nw;
3091 while (*nw != ')') {
3092 if (!*nw) {
3093 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3094 file, linenum, args[0], cw);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
3098 nw++;
3099 }
3100 *nw = '\0';
3101 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003102 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003103 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003104 if (*nw)
3105 *nw++ = '\0';
3106 type = stktable_get_data_type(cw);
3107 if (type < 0) {
3108 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3109 file, linenum, args[0], cw);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
Willy Tarreauac782882010-06-20 10:41:54 +02003113
3114 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3115 switch (err) {
3116 case PE_NONE: break;
3117 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003118 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3119 file, linenum, args[0], cw);
3120 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003121 break;
3122
3123 case PE_ARG_MISSING:
3124 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3125 file, linenum, args[0], cw);
3126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128
3129 case PE_ARG_NOT_USED:
3130 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3131 file, linenum, args[0], cw);
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
3134
3135 default:
3136 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3137 file, linenum, args[0], cw);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003140 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003141 }
3142 myidx++;
3143 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003144 else {
3145 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3146 file, linenum, args[myidx]);
3147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003149 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003150 }
3151
3152 if (!curproxy->table.size) {
3153 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3154 file, linenum);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158
3159 if (curproxy->table.type == (unsigned int)-1) {
3160 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3161 file, linenum);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165 }
3166 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003167 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003168 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003169 int myidx = 0;
3170 const char *name = NULL;
3171 int flags;
3172
3173 if (curproxy == &defproxy) {
3174 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
3178
3179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3180 err_code |= ERR_WARN;
3181 goto out;
3182 }
3183
3184 myidx++;
3185 if ((strcmp(args[myidx], "store") == 0) ||
3186 (strcmp(args[myidx], "store-request") == 0)) {
3187 myidx++;
3188 flags = STK_IS_STORE;
3189 }
3190 else if (strcmp(args[myidx], "store-response") == 0) {
3191 myidx++;
3192 flags = STK_IS_STORE | STK_ON_RSP;
3193 }
3194 else if (strcmp(args[myidx], "match") == 0) {
3195 myidx++;
3196 flags = STK_IS_MATCH;
3197 }
3198 else if (strcmp(args[myidx], "on") == 0) {
3199 myidx++;
3200 flags = STK_IS_MATCH | STK_IS_STORE;
3201 }
3202 else {
3203 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
3207
3208 if (*(args[myidx]) == 0) {
3209 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003214 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003215 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003216 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003217 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
3221
3222 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003223 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3224 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3225 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003226 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003227 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003228 goto out;
3229 }
3230 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003231 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3232 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3233 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003234 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003235 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003236 goto out;
3237 }
3238 }
3239
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003240 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003241 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003242
Emeric Brunb982a3d2010-01-04 15:45:53 +01003243 if (strcmp(args[myidx], "table") == 0) {
3244 myidx++;
3245 name = args[myidx++];
3246 }
3247
Willy Tarreauef6494c2010-01-28 17:12:36 +01003248 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003249 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3250 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3251 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003252 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003253 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003254 goto out;
3255 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003256 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003257 else if (*(args[myidx])) {
3258 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3259 file, linenum, args[0], args[myidx]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003261 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003262 goto out;
3263 }
Emeric Brun97679e72010-09-23 17:56:44 +02003264 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003265 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003266 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003267 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003268
Emeric Brunb982a3d2010-01-04 15:45:53 +01003269 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3270 rule->cond = cond;
3271 rule->expr = expr;
3272 rule->flags = flags;
3273 rule->table.name = name ? strdup(name) : NULL;
3274 LIST_INIT(&rule->list);
3275 if (flags & STK_ON_RSP)
3276 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3277 else
3278 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003283
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3285 curproxy->uri_auth = NULL; /* we must detach from the default config */
3286
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003287 if (!*args[1]) {
3288 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003289 } else if (!strcmp(args[1], "admin")) {
3290 struct stats_admin_rule *rule;
3291
3292 if (curproxy == &defproxy) {
3293 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297
3298 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3299 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3300 err_code |= ERR_ALERT | ERR_ABORT;
3301 goto out;
3302 }
3303
3304 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3305 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3306 file, linenum, args[0], args[1]);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003310 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3311 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3312 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003317 err_code |= warnif_cond_conflicts(cond,
3318 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3319 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003320
3321 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3322 rule->cond = cond;
3323 LIST_INIT(&rule->list);
3324 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 } else if (!strcmp(args[1], "uri")) {
3326 if (*(args[2]) == 0) {
3327 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3331 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_ABORT;
3333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
3335 } else if (!strcmp(args[1], "realm")) {
3336 if (*(args[2]) == 0) {
3337 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3341 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_ABORT;
3343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003345 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003346 unsigned interval;
3347
3348 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3349 if (err) {
3350 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3351 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003354 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_ABORT;
3357 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003358 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003359 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003360 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003361
3362 if (curproxy == &defproxy) {
3363 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
3367
3368 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3369 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3370 err_code |= ERR_ALERT | ERR_ABORT;
3371 goto out;
3372 }
3373
Willy Tarreauff011f22011-01-06 17:51:27 +01003374 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3375 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003376 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3377 file, linenum, args[0]);
3378 err_code |= ERR_WARN;
3379 }
3380
Willy Tarreauff011f22011-01-06 17:51:27 +01003381 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003382
Willy Tarreauff011f22011-01-06 17:51:27 +01003383 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003384 err_code |= ERR_ALERT | ERR_ABORT;
3385 goto out;
3386 }
3387
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003388 err_code |= warnif_cond_conflicts(rule->cond,
3389 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3390 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003391 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003392
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 } else if (!strcmp(args[1], "auth")) {
3394 if (*(args[2]) == 0) {
3395 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_ABORT;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403 } else if (!strcmp(args[1], "scope")) {
3404 if (*(args[2]) == 0) {
3405 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
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 }
3413 } else if (!strcmp(args[1], "enable")) {
3414 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003419 } else if (!strcmp(args[1], "hide-version")) {
3420 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3421 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_ABORT;
3423 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003424 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003425 } else if (!strcmp(args[1], "show-legends")) {
3426 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3427 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3428 err_code |= ERR_ALERT | ERR_ABORT;
3429 goto out;
3430 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003431 } else if (!strcmp(args[1], "show-node")) {
3432
3433 if (*args[2]) {
3434 int i;
3435 char c;
3436
3437 for (i=0; args[2][i]; i++) {
3438 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003439 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3440 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003441 break;
3442 }
3443
3444 if (!i || args[2][i]) {
3445 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3446 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3447 file, linenum, args[0], args[1]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
3451 }
3452
3453 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3454 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3455 err_code |= ERR_ALERT | ERR_ABORT;
3456 goto out;
3457 }
3458 } else if (!strcmp(args[1], "show-desc")) {
3459 char *desc = NULL;
3460
3461 if (*args[2]) {
3462 int i, len=0;
3463 char *d;
3464
3465 for(i=2; *args[i]; i++)
3466 len += strlen(args[i])+1;
3467
3468 desc = d = (char *)calloc(1, len);
3469
3470 d += sprintf(d, "%s", args[2]);
3471 for(i=3; *args[i]; i++)
3472 d += sprintf(d, " %s", args[i]);
3473 }
3474
3475 if (!*args[2] && !global.desc)
3476 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3477 file, linenum, args[1]);
3478 else {
3479 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3480 free(desc);
3481 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3482 err_code |= ERR_ALERT | ERR_ABORT;
3483 goto out;
3484 }
3485 free(desc);
3486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003488stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003489 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 +01003490 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 }
3494 }
3495 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003496 int optnum;
3497
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003498 if (*(args[1]) == '\0') {
3499 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3500 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003504
3505 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3506 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003507 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3508 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3509 file, linenum, cfg_opts[optnum].name);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
Willy Tarreau93893792009-07-23 13:19:11 +02003513 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3514 err_code |= ERR_WARN;
3515 goto out;
3516 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003517
Willy Tarreau3842f002009-06-14 11:39:52 +02003518 curproxy->no_options &= ~cfg_opts[optnum].val;
3519 curproxy->options &= ~cfg_opts[optnum].val;
3520
3521 switch (kwm) {
3522 case KWM_STD:
3523 curproxy->options |= cfg_opts[optnum].val;
3524 break;
3525 case KWM_NO:
3526 curproxy->no_options |= cfg_opts[optnum].val;
3527 break;
3528 case KWM_DEF: /* already cleared */
3529 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003530 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003531
Willy Tarreau93893792009-07-23 13:19:11 +02003532 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003533 }
3534 }
3535
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003536 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3537 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003538 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3539 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3540 file, linenum, cfg_opts2[optnum].name);
3541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
3543 }
Willy Tarreau93893792009-07-23 13:19:11 +02003544 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3545 err_code |= ERR_WARN;
3546 goto out;
3547 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003548
Willy Tarreau3842f002009-06-14 11:39:52 +02003549 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3550 curproxy->options2 &= ~cfg_opts2[optnum].val;
3551
3552 switch (kwm) {
3553 case KWM_STD:
3554 curproxy->options2 |= cfg_opts2[optnum].val;
3555 break;
3556 case KWM_NO:
3557 curproxy->no_options2 |= cfg_opts2[optnum].val;
3558 break;
3559 case KWM_DEF: /* already cleared */
3560 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003561 }
Willy Tarreau93893792009-07-23 13:19:11 +02003562 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003563 }
3564 }
3565
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003566 /* HTTP options override each other. They can be cancelled using
3567 * "no option xxx" which only switches to default mode if the mode
3568 * was this one (useful for cancelling options set in defaults
3569 * sections).
3570 */
3571 if (strcmp(args[1], "httpclose") == 0) {
3572 if (kwm == KWM_STD) {
3573 curproxy->options &= ~PR_O_HTTP_MODE;
3574 curproxy->options |= PR_O_HTTP_PCL;
3575 goto out;
3576 }
3577 else if (kwm == KWM_NO) {
3578 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3579 curproxy->options &= ~PR_O_HTTP_MODE;
3580 goto out;
3581 }
3582 }
3583 else if (strcmp(args[1], "forceclose") == 0) {
3584 if (kwm == KWM_STD) {
3585 curproxy->options &= ~PR_O_HTTP_MODE;
3586 curproxy->options |= PR_O_HTTP_FCL;
3587 goto out;
3588 }
3589 else if (kwm == KWM_NO) {
3590 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3591 curproxy->options &= ~PR_O_HTTP_MODE;
3592 goto out;
3593 }
3594 }
3595 else if (strcmp(args[1], "http-server-close") == 0) {
3596 if (kwm == KWM_STD) {
3597 curproxy->options &= ~PR_O_HTTP_MODE;
3598 curproxy->options |= PR_O_HTTP_SCL;
3599 goto out;
3600 }
3601 else if (kwm == KWM_NO) {
3602 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3603 curproxy->options &= ~PR_O_HTTP_MODE;
3604 goto out;
3605 }
3606 }
3607 else if (strcmp(args[1], "http-keep-alive") == 0) {
3608 if (kwm == KWM_STD) {
3609 curproxy->options &= ~PR_O_HTTP_MODE;
3610 curproxy->options |= PR_O_HTTP_KAL;
3611 goto out;
3612 }
3613 else if (kwm == KWM_NO) {
3614 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3615 curproxy->options &= ~PR_O_HTTP_MODE;
3616 goto out;
3617 }
3618 }
3619 else if (strcmp(args[1], "http-tunnel") == 0) {
3620 if (kwm == KWM_STD) {
3621 curproxy->options &= ~PR_O_HTTP_MODE;
3622 curproxy->options |= PR_O_HTTP_TUN;
3623 goto out;
3624 }
3625 else if (kwm == KWM_NO) {
3626 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3627 curproxy->options &= ~PR_O_HTTP_MODE;
3628 goto out;
3629 }
3630 }
3631
Willy Tarreau3842f002009-06-14 11:39:52 +02003632 if (kwm != KWM_STD) {
3633 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003634 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003637 }
3638
Emeric Brun3a058f32009-06-30 18:26:00 +02003639 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003640 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003642 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003643 if (*(args[2]) != '\0') {
3644 if (!strcmp(args[2], "clf")) {
3645 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003646 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003647 } else {
3648 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003651 }
3652 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003653 if (curproxy->conf.logformat_string != default_http_log_format &&
3654 curproxy->conf.logformat_string != default_tcp_log_format &&
3655 curproxy->conf.logformat_string != clf_http_log_format)
3656 free(curproxy->conf.logformat_string);
3657 curproxy->conf.logformat_string = logformat;
3658
3659 free(curproxy->conf.lfs_file);
3660 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3661 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003662 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003663 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003665 if (curproxy->conf.logformat_string != default_http_log_format &&
3666 curproxy->conf.logformat_string != default_tcp_log_format &&
3667 curproxy->conf.logformat_string != clf_http_log_format)
3668 free(curproxy->conf.logformat_string);
3669 curproxy->conf.logformat_string = default_tcp_log_format;
3670
3671 free(curproxy->conf.lfs_file);
3672 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3673 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 else if (!strcmp(args[1], "tcpka")) {
3676 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003677 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003678 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003679
3680 if (curproxy->cap & PR_CAP_FE)
3681 curproxy->options |= PR_O_TCP_CLI_KA;
3682 if (curproxy->cap & PR_CAP_BE)
3683 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 }
3685 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003686 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_WARN;
3688
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003690 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003691 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003692 curproxy->options2 &= ~PR_O2_CHK_ANY;
3693 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 if (!*args[2]) { /* no argument */
3695 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3696 curproxy->check_len = strlen(DEF_CHECK_REQ);
3697 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003698 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 curproxy->check_req = (char *)malloc(reqlen);
3700 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003701 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003703 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 if (*args[4])
3705 reqlen += strlen(args[4]);
3706 else
3707 reqlen += strlen("HTTP/1.0");
3708
3709 curproxy->check_req = (char *)malloc(reqlen);
3710 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003711 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003713 }
3714 else if (!strcmp(args[1], "ssl-hello-chk")) {
3715 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003718
Willy Tarreaua534fea2008-08-03 12:19:50 +02003719 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003720 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003721 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003722 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
Willy Tarreau23677902007-05-08 23:50:35 +02003724 else if (!strcmp(args[1], "smtpchk")) {
3725 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003726 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003727 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003728 curproxy->options2 &= ~PR_O2_CHK_ANY;
3729 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003730
3731 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3732 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3733 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3734 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3735 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3736 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3737 curproxy->check_req = (char *)malloc(reqlen);
3738 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3739 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3740 } else {
3741 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3742 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3743 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3744 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3745 }
3746 }
3747 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003748 else if (!strcmp(args[1], "pgsql-check")) {
3749 /* use PostgreSQL request to check servers' health */
3750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3751 err_code |= ERR_WARN;
3752
3753 free(curproxy->check_req);
3754 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003755 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003756 curproxy->options2 |= PR_O2_PGSQL_CHK;
3757
3758 if (*(args[2])) {
3759 int cur_arg = 2;
3760
3761 while (*(args[cur_arg])) {
3762 if (strcmp(args[cur_arg], "user") == 0) {
3763 char * packet;
3764 uint32_t packet_len;
3765 uint32_t pv;
3766
3767 /* suboption header - needs additional argument for it */
3768 if (*(args[cur_arg+1]) == 0) {
3769 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3770 file, linenum, args[0], args[1], args[cur_arg]);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
3774
3775 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3776 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3777 pv = htonl(0x30000); /* protocol version 3.0 */
3778
3779 packet = (char*) calloc(1, packet_len);
3780
3781 memcpy(packet + 4, &pv, 4);
3782
3783 /* copy "user" */
3784 memcpy(packet + 8, "user", 4);
3785
3786 /* copy username */
3787 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3788
3789 free(curproxy->check_req);
3790 curproxy->check_req = packet;
3791 curproxy->check_len = packet_len;
3792
3793 packet_len = htonl(packet_len);
3794 memcpy(packet, &packet_len, 4);
3795 cur_arg += 2;
3796 } else {
3797 /* unknown suboption - catchall */
3798 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3799 file, linenum, args[0], args[1]);
3800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
3802 }
3803 } /* end while loop */
3804 }
3805 }
3806
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003807 else if (!strcmp(args[1], "redis-check")) {
3808 /* use REDIS PING request to check servers' health */
3809 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3810 err_code |= ERR_WARN;
3811
3812 free(curproxy->check_req);
3813 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003814 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003815 curproxy->options2 |= PR_O2_REDIS_CHK;
3816
3817 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3818 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3819 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3820 }
3821
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003822 else if (!strcmp(args[1], "mysql-check")) {
3823 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3825 err_code |= ERR_WARN;
3826
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003827 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003828 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003829 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003830 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003831
3832 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3833 * const char mysql40_client_auth_pkt[] = {
3834 * "\x0e\x00\x00" // packet length
3835 * "\x01" // packet number
3836 * "\x00\x00" // client capabilities
3837 * "\x00\x00\x01" // max packet
3838 * "haproxy\x00" // username (null terminated string)
3839 * "\x00" // filler (always 0x00)
3840 * "\x01\x00\x00" // packet length
3841 * "\x00" // packet number
3842 * "\x01" // COM_QUIT command
3843 * };
3844 */
3845
3846 if (*(args[2])) {
3847 int cur_arg = 2;
3848
3849 while (*(args[cur_arg])) {
3850 if (strcmp(args[cur_arg], "user") == 0) {
3851 char *mysqluser;
3852 int packetlen, reqlen, userlen;
3853
3854 /* suboption header - needs additional argument for it */
3855 if (*(args[cur_arg+1]) == 0) {
3856 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3857 file, linenum, args[0], args[1], args[cur_arg]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861 mysqluser = args[cur_arg + 1];
3862 userlen = strlen(mysqluser);
3863 packetlen = userlen + 7;
3864 reqlen = packetlen + 9;
3865
3866 free(curproxy->check_req);
3867 curproxy->check_req = (char *)calloc(1, reqlen);
3868 curproxy->check_len = reqlen;
3869
3870 snprintf(curproxy->check_req, 4, "%c%c%c",
3871 ((unsigned char) packetlen & 0xff),
3872 ((unsigned char) (packetlen >> 8) & 0xff),
3873 ((unsigned char) (packetlen >> 16) & 0xff));
3874
3875 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003876 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003877 curproxy->check_req[8] = 1;
3878 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3879 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3880 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3881 cur_arg += 2;
3882 } else {
3883 /* unknown suboption - catchall */
3884 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3885 file, linenum, args[0], args[1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 } /* end while loop */
3890 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003891 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003892 else if (!strcmp(args[1], "ldap-check")) {
3893 /* use LDAP request to check servers' health */
3894 free(curproxy->check_req);
3895 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003896 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003897 curproxy->options2 |= PR_O2_LDAP_CHK;
3898
3899 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3900 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3901 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3902 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003903 else if (!strcmp(args[1], "tcp-check")) {
3904 /* use raw TCPCHK send/expect to check servers' health */
3905 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3906 err_code |= ERR_WARN;
3907
3908 free(curproxy->check_req);
3909 curproxy->check_req = NULL;
3910 curproxy->options2 &= ~PR_O2_CHK_ANY;
3911 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3912 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003913 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003914 int cur_arg;
3915
3916 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3917 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003918 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003919
Willy Tarreau87cf5142011-08-19 22:57:24 +02003920 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003921
3922 free(curproxy->fwdfor_hdr_name);
3923 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3924 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3925
3926 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3927 cur_arg = 2;
3928 while (*(args[cur_arg])) {
3929 if (!strcmp(args[cur_arg], "except")) {
3930 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003931 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003932 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3933 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003936 }
3937 /* flush useless bits */
3938 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003939 cur_arg += 2;
3940 } else if (!strcmp(args[cur_arg], "header")) {
3941 /* suboption header - needs additional argument for it */
3942 if (*(args[cur_arg+1]) == 0) {
3943 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3944 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003947 }
3948 free(curproxy->fwdfor_hdr_name);
3949 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3950 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3951 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003952 } else if (!strcmp(args[cur_arg], "if-none")) {
3953 curproxy->options &= ~PR_O_FF_ALWAYS;
3954 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003955 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003956 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003957 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003958 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003961 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003962 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003963 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003964 else if (!strcmp(args[1], "originalto")) {
3965 int cur_arg;
3966
3967 /* insert x-original-to field, but not for the IP address listed as an except.
3968 * set default options (ie: bitfield, header name, etc)
3969 */
3970
3971 curproxy->options |= PR_O_ORGTO;
3972
3973 free(curproxy->orgto_hdr_name);
3974 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3975 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3976
Willy Tarreau87cf5142011-08-19 22:57:24 +02003977 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003978 cur_arg = 2;
3979 while (*(args[cur_arg])) {
3980 if (!strcmp(args[cur_arg], "except")) {
3981 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003982 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
Maik Broemme2850cb42009-04-17 18:53:21 +02003983 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3984 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003987 }
3988 /* flush useless bits */
3989 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3990 cur_arg += 2;
3991 } else if (!strcmp(args[cur_arg], "header")) {
3992 /* suboption header - needs additional argument for it */
3993 if (*(args[cur_arg+1]) == 0) {
3994 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3995 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003998 }
3999 free(curproxy->orgto_hdr_name);
4000 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4001 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4002 cur_arg += 2;
4003 } else {
4004 /* unknown suboption - catchall */
4005 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4006 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004009 }
4010 } /* end while loop */
4011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 else {
4013 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 }
Willy Tarreau93893792009-07-23 13:19:11 +02004017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004019 else if (!strcmp(args[0], "default_backend")) {
4020 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004022
4023 if (*(args[1]) == 0) {
4024 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004027 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004028 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004029 curproxy->defbe.name = strdup(args[1]);
4030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004032 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004033 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004034
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004035 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4036 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 /* enable reconnections to dispatch */
4039 curproxy->options |= PR_O_REDISP;
4040 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004041 else if (!strcmp(args[0], "http-check")) {
4042 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004044
4045 if (strcmp(args[1], "disable-on-404") == 0) {
4046 /* enable a graceful server shutdown on an HTTP 404 response */
4047 curproxy->options |= PR_O_DISABLE404;
4048 }
Willy Tarreauef781042010-01-27 11:53:01 +01004049 else if (strcmp(args[1], "send-state") == 0) {
4050 /* enable emission of the apparent state of a server in HTTP checks */
4051 curproxy->options2 |= PR_O2_CHK_SNDST;
4052 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004053 else if (strcmp(args[1], "expect") == 0) {
4054 const char *ptr_arg;
4055 int cur_arg;
4056
4057 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4058 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062
4063 cur_arg = 2;
4064 /* consider exclamation marks, sole or at the beginning of a word */
4065 while (*(ptr_arg = args[cur_arg])) {
4066 while (*ptr_arg == '!') {
4067 curproxy->options2 ^= PR_O2_EXP_INV;
4068 ptr_arg++;
4069 }
4070 if (*ptr_arg)
4071 break;
4072 cur_arg++;
4073 }
4074 /* now ptr_arg points to the beginning of a word past any possible
4075 * exclamation mark, and cur_arg is the argument which holds this word.
4076 */
4077 if (strcmp(ptr_arg, "status") == 0) {
4078 if (!*(args[cur_arg + 1])) {
4079 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4080 file, linenum, args[0], args[1], ptr_arg);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004085 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004086 curproxy->expect_str = strdup(args[cur_arg + 1]);
4087 }
4088 else if (strcmp(ptr_arg, "string") == 0) {
4089 if (!*(args[cur_arg + 1])) {
4090 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4091 file, linenum, args[0], args[1], ptr_arg);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004096 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004097 curproxy->expect_str = strdup(args[cur_arg + 1]);
4098 }
4099 else if (strcmp(ptr_arg, "rstatus") == 0) {
4100 if (!*(args[cur_arg + 1])) {
4101 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4102 file, linenum, args[0], args[1], ptr_arg);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004107 free(curproxy->expect_str);
4108 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4109 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004110 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4111 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4112 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4113 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
4116 }
4117 }
4118 else if (strcmp(ptr_arg, "rstring") == 0) {
4119 if (!*(args[cur_arg + 1])) {
4120 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4121 file, linenum, args[0], args[1], ptr_arg);
4122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
4124 }
4125 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004126 free(curproxy->expect_str);
4127 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4128 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004129 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4130 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4131 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4132 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 }
4137 else {
4138 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4139 file, linenum, args[0], args[1], ptr_arg);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004144 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004145 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 +02004146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004148 }
4149 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004150 else if (!strcmp(args[0], "tcp-check")) {
4151 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4152 err_code |= ERR_WARN;
4153
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004154 if (strcmp(args[1], "connect") == 0) {
4155 const char *ptr_arg;
4156 int cur_arg;
4157 struct tcpcheck_rule *tcpcheck;
4158 struct list *l;
4159
4160 /* check if first rule is also a 'connect' action */
4161 l = (struct list *)&curproxy->tcpcheck_rules;
4162 if (l->p != l->n) {
4163 tcpcheck = (struct tcpcheck_rule *)l->n;
4164 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4165 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4166 file, linenum);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170 }
4171
4172 cur_arg = 2;
4173 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4174 tcpcheck->action = TCPCHK_ACT_CONNECT;
4175
4176 /* parsing each parameters to fill up the rule */
4177 while (*(ptr_arg = args[cur_arg])) {
4178 /* tcp port */
4179 if (strcmp(args[cur_arg], "port") == 0) {
4180 if ( (atol(args[cur_arg + 1]) > 65535) ||
4181 (atol(args[cur_arg + 1]) < 1) ){
4182 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4183 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187 tcpcheck->port = atol(args[cur_arg + 1]);
4188 cur_arg += 2;
4189 }
4190 /* send proxy protocol */
4191 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4192 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4193 cur_arg++;
4194 }
4195#ifdef USE_OPENSSL
4196 else if (strcmp(args[cur_arg], "ssl") == 0) {
4197 curproxy->options |= PR_O_TCPCHK_SSL;
4198 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4199 cur_arg++;
4200 }
4201#endif /* USE_OPENSSL */
4202 else {
4203#ifdef USE_OPENSSL
4204 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4205#else /* USE_OPENSSL */
4206 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4207#endif /* USE_OPENSSL */
4208 file, linenum, args[0], args[1], args[cur_arg]);
4209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
4211 }
4212
4213 }
4214
4215 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4216 }
4217 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004218 if (! *(args[2]) ) {
4219 /* SEND string expected */
4220 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4221 file, linenum, args[0], args[1], args[2]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 } else {
4225 struct tcpcheck_rule *tcpcheck;
4226
4227 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4228
4229 tcpcheck->action = TCPCHK_ACT_SEND;
4230 tcpcheck->string_len = strlen(args[2]);
4231 tcpcheck->string = strdup(args[2]);
4232 tcpcheck->expect_regex = NULL;
4233
4234 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4235 }
4236 }
4237 else if (strcmp(args[1], "send-binary") == 0) {
4238 if (! *(args[2]) ) {
4239 /* SEND binary string expected */
4240 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4241 file, linenum, args[0], args[1], args[2]);
4242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
4244 } else {
4245 struct tcpcheck_rule *tcpcheck;
4246 char *err = NULL;
4247
4248 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4249
4250 tcpcheck->action = TCPCHK_ACT_SEND;
4251 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4252 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4253 file, linenum, args[0], args[1], args[2], err);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257 tcpcheck->expect_regex = NULL;
4258
4259 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4260 }
4261 }
4262 else if (strcmp(args[1], "expect") == 0) {
4263 const char *ptr_arg;
4264 int cur_arg;
4265 int inverse = 0;
4266
4267 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4268 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272
4273 cur_arg = 2;
4274 /* consider exclamation marks, sole or at the beginning of a word */
4275 while (*(ptr_arg = args[cur_arg])) {
4276 while (*ptr_arg == '!') {
4277 inverse = !inverse;
4278 ptr_arg++;
4279 }
4280 if (*ptr_arg)
4281 break;
4282 cur_arg++;
4283 }
4284 /* now ptr_arg points to the beginning of a word past any possible
4285 * exclamation mark, and cur_arg is the argument which holds this word.
4286 */
4287 if (strcmp(ptr_arg, "binary") == 0) {
4288 if (!*(args[cur_arg + 1])) {
4289 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4290 file, linenum, args[0], args[1], ptr_arg);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294 struct tcpcheck_rule *tcpcheck;
4295 char *err = NULL;
4296
4297 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4298
4299 tcpcheck->action = TCPCHK_ACT_EXPECT;
4300 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4301 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4302 file, linenum, args[0], args[1], args[2], err);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306 tcpcheck->expect_regex = NULL;
4307 tcpcheck->inverse = inverse;
4308
4309 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4310 }
4311 else if (strcmp(ptr_arg, "string") == 0) {
4312 if (!*(args[cur_arg + 1])) {
4313 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4314 file, linenum, args[0], args[1], ptr_arg);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 struct tcpcheck_rule *tcpcheck;
4319
4320 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4321
4322 tcpcheck->action = TCPCHK_ACT_EXPECT;
4323 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4324 tcpcheck->string = strdup(args[cur_arg + 1]);
4325 tcpcheck->expect_regex = NULL;
4326 tcpcheck->inverse = inverse;
4327
4328 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4329 }
4330 else if (strcmp(ptr_arg, "rstring") == 0) {
4331 if (!*(args[cur_arg + 1])) {
4332 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4333 file, linenum, args[0], args[1], ptr_arg);
4334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
4336 }
4337 struct tcpcheck_rule *tcpcheck;
4338
4339 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4340
4341 tcpcheck->action = TCPCHK_ACT_EXPECT;
4342 tcpcheck->string_len = 0;
4343 tcpcheck->string = NULL;
4344 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4345 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4346 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4347 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
4350 }
4351 tcpcheck->inverse = inverse;
4352
4353 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4354 }
4355 else {
4356 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4357 file, linenum, args[0], args[1], ptr_arg);
4358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
4360 }
4361 }
4362 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004363 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
4366 }
4367 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004368 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004369 if (curproxy == &defproxy) {
4370 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004373 }
4374
Willy Tarreaub80c2302007-11-30 20:51:32 +01004375 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004377
4378 if (strcmp(args[1], "fail") == 0) {
4379 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004380 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004381 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4382 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004385 }
4386
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004387 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4388 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4389 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004392 }
4393 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4394 }
4395 else {
4396 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004399 }
4400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401#ifdef TPROXY
4402 else if (!strcmp(args[0], "transparent")) {
4403 /* enable transparent proxy connections */
4404 curproxy->options |= PR_O_TRANSP;
4405 }
4406#endif
4407 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004408 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004410
Willy Tarreaubaaee002006-06-26 02:48:02 +02004411 if (*(args[1]) == 0) {
4412 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 }
4416 curproxy->maxconn = atol(args[1]);
4417 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004418 else if (!strcmp(args[0], "backlog")) { /* backlog */
4419 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004421
4422 if (*(args[1]) == 0) {
4423 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004426 }
4427 curproxy->backlog = atol(args[1]);
4428 }
Willy Tarreau86034312006-12-29 00:10:33 +01004429 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004432
Willy Tarreau86034312006-12-29 00:10:33 +01004433 if (*(args[1]) == 0) {
4434 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004437 }
4438 curproxy->fullconn = atol(args[1]);
4439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4441 if (*(args[1]) == 0) {
4442 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004446 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4447 if (err) {
4448 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4449 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004452 }
4453 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 }
4455 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004456 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004457 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004458 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004459
Willy Tarreaubaaee002006-06-26 02:48:02 +02004460 if (curproxy == &defproxy) {
4461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004465 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004467
Willy Tarreau902636f2013-03-10 19:44:48 +01004468 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004469 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004470 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004471 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004472 goto out;
4473 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004474
4475 proto = protocol_by_family(sk->ss_family);
4476 if (!proto || !proto->connect) {
4477 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4478 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
4481 }
4482
4483 if (port1 != port2) {
4484 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4485 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004489
4490 if (!port1) {
4491 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4492 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004496
Willy Tarreaud5191e72010-02-09 20:50:45 +01004497 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004498 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 }
4500 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004501 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004502 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004503
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004504 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4505 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004510 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004511 /**
4512 * The syntax for hash-type config element is
4513 * hash-type {map-based|consistent} [[<algo>] avalanche]
4514 *
4515 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4516 */
4517 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004518
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4520 err_code |= ERR_WARN;
4521
4522 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004523 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4524 }
4525 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004526 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4527 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004528 else if (strcmp(args[1], "avalanche") == 0) {
4529 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]);
4530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004532 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004533 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004534 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
Bhaskar98634f02013-10-29 23:30:51 -04004538
4539 /* set the hash function to use */
4540 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004541 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004542 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004543
4544 /* if consistent with no argument, then avalanche modifier is also applied */
4545 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4546 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004547 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004548 /* set the hash function */
4549 if (!strcmp(args[2], "sdbm")) {
4550 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4551 }
4552 else if (!strcmp(args[2], "djb2")) {
4553 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004554 } else if (!strcmp(args[2], "wt6")) {
4555 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004556 }
4557 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004558 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 -05004559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
4561 }
4562
4563 /* set the hash modifier */
4564 if (!strcmp(args[3], "avalanche")) {
4565 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4566 }
4567 else if (*args[3]) {
4568 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
4571 }
Bhaskar98634f02013-10-29 23:30:51 -04004572 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004573 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004574 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004576 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004577 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004579 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004584 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586
4587 if (!*args[2]) {
4588 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4589 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004593
4594 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004595 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004596 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4597 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004600 }
4601
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004602 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004603 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004604 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004605 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004606
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004607 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4608 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4609 err_code |= ERR_ALERT | ERR_ABORT;
4610 goto out;
4611 }
4612
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004613 /* the servers are linked backwards first */
4614 newsrv->next = curproxy->srv;
4615 curproxy->srv = newsrv;
4616 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004617 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004618 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004620 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004621 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004622 LIST_INIT(&newsrv->pendconns);
4623 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004624 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004625 newsrv->state = SRV_RUNNING; /* early server setup */
4626 newsrv->last_change = now.tv_sec;
4627 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004629 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004630 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004631 * - IP: => port=+0, relative
4632 * - IP:N => port=N, absolute
4633 * - IP:+N => port=+N, relative
4634 * - IP:-N => port=-N, relative
4635 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004636 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004637 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004638 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004639 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004640 goto out;
4641 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004642
4643 proto = protocol_by_family(sk->ss_family);
4644 if (!proto || !proto->connect) {
4645 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4646 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004650
4651 if (!port1 || !port2) {
4652 /* no port specified, +offset, -offset */
4653 newsrv->state |= SRV_MAPPORTS;
4654 }
4655 else if (port1 != port2) {
4656 /* port range */
4657 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4658 file, linenum, args[0], args[1], args[2]);
4659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
4661 }
4662 else {
4663 /* used by checks */
4664 realport = port1;
4665 }
4666
Willy Tarreaud5191e72010-02-09 20:50:45 +01004667 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004668 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4669 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004670
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004671 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004672 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4673 file, linenum, newsrv->addr.ss_family, args[2]);
4674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004677
Simon Hormand60d6912013-11-25 10:46:36 +09004678 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004679 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004680 newsrv->check.inter = curproxy->defsrv.check.inter;
4681 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4682 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004683 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4684 newsrv->agent.port = curproxy->defsrv.agent.port;
4685 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4686 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4687 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004688 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4689 newsrv->minconn = curproxy->defsrv.minconn;
4690 newsrv->maxconn = curproxy->defsrv.maxconn;
4691 newsrv->slowstart = curproxy->defsrv.slowstart;
4692 newsrv->onerror = curproxy->defsrv.onerror;
Willy Tarreauabd03df2014-02-18 10:36:15 +01004693 newsrv->onmarkeddown = curproxy->defsrv.onmarkeddown;
4694 newsrv->onmarkedup = curproxy->defsrv.onmarkedup;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004695 newsrv->consecutive_errors_limit
4696 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004697#ifdef OPENSSL
4698 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4699#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004700 newsrv->uweight = newsrv->iweight
4701 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702
Simon Horman69d29f92013-02-23 15:14:19 +09004703 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004704 newsrv->check.rise = curproxy->defsrv.check.rise;
4705 newsrv->check.fall = curproxy->defsrv.check.fall;
4706 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004707 newsrv->check.server = newsrv;
4708
Simon Hormand60d6912013-11-25 10:46:36 +09004709 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004710 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4711 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4712 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004713 newsrv->agent.server = newsrv;
4714
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004715 cur_arg = 3;
4716 } else {
4717 newsrv = &curproxy->defsrv;
4718 cur_arg = 1;
4719 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004720
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004722 if (!strcmp(args[cur_arg], "agent-check")) {
4723 global.maxsock++;
4724 do_agent = 1;
4725 cur_arg += 1;
4726 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4727 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4728 if (err) {
4729 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4730 file, linenum, *err, newsrv->id);
4731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
4733 }
4734 if (val <= 0) {
4735 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4736 file, linenum, val, args[cur_arg], newsrv->id);
4737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
4740 newsrv->agent.inter = val;
4741 cur_arg += 2;
4742 }
4743 else if (!strcmp(args[cur_arg], "agent-port")) {
4744 global.maxsock++;
4745 newsrv->agent.port = atol(args[cur_arg + 1]);
4746 cur_arg += 2;
4747 }
4748 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 newsrv->cookie = strdup(args[cur_arg + 1]);
4750 newsrv->cklen = strlen(args[cur_arg + 1]);
4751 cur_arg += 2;
4752 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004753 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004754 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4755 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4756 cur_arg += 2;
4757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004759 if (!*args[cur_arg + 1]) {
4760 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4761 file, linenum, args[cur_arg]);
4762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
4764 }
4765
Simon Horman58c32972013-11-25 10:46:38 +09004766 newsrv->check.rise = atol(args[cur_arg + 1]);
4767 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004768 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4769 file, linenum, args[cur_arg]);
4770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
4773
Simon Horman125d0992013-02-24 17:23:38 +09004774 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004775 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 cur_arg += 2;
4777 }
4778 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004779 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004780
4781 if (!*args[cur_arg + 1]) {
4782 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4783 file, linenum, args[cur_arg]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786 }
4787
Simon Horman58c32972013-11-25 10:46:38 +09004788 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004789 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4790 file, linenum, args[cur_arg]);
4791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
4793 }
4794
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 cur_arg += 2;
4796 }
4797 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004798 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4799 if (err) {
4800 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4801 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004804 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004805 if (val <= 0) {
4806 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4807 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004810 }
Simon Horman66183002013-02-23 10:16:43 +09004811 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 cur_arg += 2;
4813 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004814 else if (!strcmp(args[cur_arg], "fastinter")) {
4815 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4816 if (err) {
4817 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4818 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004821 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004822 if (val <= 0) {
4823 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4824 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004827 }
Simon Horman66183002013-02-23 10:16:43 +09004828 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004829 cur_arg += 2;
4830 }
4831 else if (!strcmp(args[cur_arg], "downinter")) {
4832 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4833 if (err) {
4834 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4835 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004838 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004839 if (val <= 0) {
4840 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4841 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004844 }
Simon Horman66183002013-02-23 10:16:43 +09004845 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004846 cur_arg += 2;
4847 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004848 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004849 struct sockaddr_storage *sk;
4850 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004851 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004852
Willy Tarreau902636f2013-03-10 19:44:48 +01004853 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004854 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004855 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004856 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004857 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004858 goto out;
4859 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004860
4861 proto = protocol_by_family(sk->ss_family);
4862 if (!proto || !proto->connect) {
4863 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004864 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004868
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004869 if (port1 != port2) {
4870 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4871 file, linenum, args[cur_arg], args[cur_arg + 1]);
4872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
4874 }
4875
Simon Horman66183002013-02-23 10:16:43 +09004876 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004877 cur_arg += 2;
4878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004880 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 cur_arg += 2;
4882 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004883 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 newsrv->state |= SRV_BACKUP;
4885 cur_arg ++;
4886 }
Simon Hormanfa461682011-06-25 09:39:49 +09004887 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4888 newsrv->state |= SRV_NON_STICK;
4889 cur_arg ++;
4890 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004891 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4892 newsrv->state |= SRV_SEND_PROXY;
4893 cur_arg ++;
4894 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004895 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4896 newsrv->check.send_proxy = 1;
4897 cur_arg ++;
4898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 else if (!strcmp(args[cur_arg], "weight")) {
4900 int w;
4901 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004902 if (w < 0 || w > SRV_UWGHT_MAX) {
4903 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4904 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004908 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 cur_arg += 2;
4910 }
4911 else if (!strcmp(args[cur_arg], "minconn")) {
4912 newsrv->minconn = atol(args[cur_arg + 1]);
4913 cur_arg += 2;
4914 }
4915 else if (!strcmp(args[cur_arg], "maxconn")) {
4916 newsrv->maxconn = atol(args[cur_arg + 1]);
4917 cur_arg += 2;
4918 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004919 else if (!strcmp(args[cur_arg], "maxqueue")) {
4920 newsrv->maxqueue = atol(args[cur_arg + 1]);
4921 cur_arg += 2;
4922 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004923 else if (!strcmp(args[cur_arg], "slowstart")) {
4924 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004925 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004926 if (err) {
4927 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4928 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004931 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004932 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004933 cur_arg += 2;
4934 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004935 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004936
4937 if (!*args[cur_arg + 1]) {
4938 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4939 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004942 }
4943
4944 newsrv->trackit = strdup(args[cur_arg + 1]);
4945
4946 cur_arg += 2;
4947 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004948 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 global.maxsock++;
4950 do_check = 1;
4951 cur_arg += 1;
4952 }
Willy Tarreau96839092010-03-29 10:02:24 +02004953 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4954 newsrv->state |= SRV_MAINTAIN;
4955 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004956 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004957 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004958 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004959 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004960 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004961 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004962 if (!strcmp(args[cur_arg + 1], "none"))
4963 newsrv->observe = HANA_OBS_NONE;
4964 else if (!strcmp(args[cur_arg + 1], "layer4"))
4965 newsrv->observe = HANA_OBS_LAYER4;
4966 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4967 if (curproxy->mode != PR_MODE_HTTP) {
4968 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4969 file, linenum, args[cur_arg + 1]);
4970 err_code |= ERR_ALERT;
4971 }
4972 newsrv->observe = HANA_OBS_LAYER7;
4973 }
4974 else {
4975 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004976 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004977 file, linenum, args[cur_arg], args[cur_arg + 1]);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981
4982 cur_arg += 2;
4983 }
4984 else if (!strcmp(args[cur_arg], "on-error")) {
4985 if (!strcmp(args[cur_arg + 1], "fastinter"))
4986 newsrv->onerror = HANA_ONERR_FASTINTER;
4987 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4988 newsrv->onerror = HANA_ONERR_FAILCHK;
4989 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4990 newsrv->onerror = HANA_ONERR_SUDDTH;
4991 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4992 newsrv->onerror = HANA_ONERR_MARKDWN;
4993 else {
4994 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004995 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004996 file, linenum, args[cur_arg], args[cur_arg + 1]);
4997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
4999 }
5000
5001 cur_arg += 2;
5002 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09005003 else if (!strcmp(args[cur_arg], "on-marked-down")) {
5004 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
5005 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
5006 else {
5007 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
5008 file, linenum, args[cur_arg], args[cur_arg + 1]);
5009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
5011 }
5012
5013 cur_arg += 2;
5014 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07005015 else if (!strcmp(args[cur_arg], "on-marked-up")) {
5016 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
5017 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
5018 else {
5019 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
5020 file, linenum, args[cur_arg], args[cur_arg + 1]);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
5024
5025 cur_arg += 2;
5026 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005027 else if (!strcmp(args[cur_arg], "error-limit")) {
5028 if (!*args[cur_arg + 1]) {
5029 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
5030 file, linenum, args[cur_arg]);
5031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
5033 }
5034
5035 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
5036
5037 if (newsrv->consecutive_errors_limit <= 0) {
5038 Alert("parsing [%s:%d]: %s has to be > 0.\n",
5039 file, linenum, args[cur_arg]);
5040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
5042 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01005043 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005044 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005045 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005046 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005047 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005048 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01005049
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01005051 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
5052 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005056
Willy Tarreauef9a3602012-12-08 22:29:20 +01005057 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01005058 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005059 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005060 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005061 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005062 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005063 goto out;
5064 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005065
5066 proto = protocol_by_family(sk->ss_family);
5067 if (!proto || !proto->connect) {
5068 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5069 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
5072 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005073
Willy Tarreauef9a3602012-12-08 22:29:20 +01005074 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005075
5076 if (port_low != port_high) {
5077 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005078
5079 if (!port_low || !port_high) {
5080 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
5081 file, linenum, args[cur_arg], args[cur_arg + 1]);
5082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
5084 }
5085
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005086 if (port_low <= 0 || port_low > 65535 ||
5087 port_high <= 0 || port_high > 65535 ||
5088 port_low > port_high) {
5089 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
5090 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005093 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005094 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
5095 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
5096 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005097 }
5098
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005100 while (*(args[cur_arg])) {
5101 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005102#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5103#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005104 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01005105 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
5106 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005109 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005110#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005111 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005112 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01005113 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005116 }
5117 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005118 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5119 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005120 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005121 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5122 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005123 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5124 char *name, *end;
5125
5126 name = args[cur_arg+1] + 7;
5127 while (isspace(*name))
5128 name++;
5129
5130 end = name;
5131 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5132 end++;
5133
Willy Tarreauef9a3602012-12-08 22:29:20 +01005134 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5135 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5136 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5137 newsrv->conn_src.bind_hdr_len = end - name;
5138 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5139 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5140 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005141
5142 /* now look for an occurrence number */
5143 while (isspace(*end))
5144 end++;
5145 if (*end == ',') {
5146 end++;
5147 name = end;
5148 if (*end == '-')
5149 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005150 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005151 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005152 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005153 }
5154
Willy Tarreauef9a3602012-12-08 22:29:20 +01005155 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005156 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5157 " occurrences values smaller than %d.\n",
5158 file, linenum, MAX_HDR_HISTORY);
5159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
5161 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005162 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005163 struct sockaddr_storage *sk;
5164 int port1, port2;
5165
Willy Tarreau902636f2013-03-10 19:44:48 +01005166 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005167 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005168 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005169 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005170 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005171 goto out;
5172 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005173
5174 proto = protocol_by_family(sk->ss_family);
5175 if (!proto || !proto->connect) {
5176 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5177 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
5180 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005181
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005182 if (port1 != port2) {
5183 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5184 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
5187 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005188 newsrv->conn_src.tproxy_addr = *sk;
5189 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005190 }
5191 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005192#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005193 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005194#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005195 cur_arg += 2;
5196 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005197#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005198 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005199 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005202#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005203 } /* "usesrc" */
5204
5205 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5206#ifdef SO_BINDTODEVICE
5207 if (!*args[cur_arg + 1]) {
5208 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5209 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005212 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005213 free(newsrv->conn_src.iface_name);
5214 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5215 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005216 global.last_checks |= LSTCHK_NETADM;
5217#else
5218 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5219 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005222#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005223 cur_arg += 2;
5224 continue;
5225 }
5226 /* this keyword in not an option of "source" */
5227 break;
5228 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005230 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005231 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5232 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005237 static int srv_dumped;
5238 struct srv_kw *kw;
5239 char *err;
5240
5241 kw = srv_find_kw(args[cur_arg]);
5242 if (kw) {
5243 char *err = NULL;
5244 int code;
5245
5246 if (!kw->parse) {
5247 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5248 file, linenum, args[0], args[1], args[cur_arg]);
5249 cur_arg += 1 + kw->skip ;
5250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
5252 }
5253
5254 if (defsrv && !kw->default_ok) {
5255 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5256 file, linenum, args[0], args[1], args[cur_arg]);
5257 cur_arg += 1 + kw->skip ;
5258 err_code |= ERR_ALERT;
5259 continue;
5260 }
5261
5262 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5263 err_code |= code;
5264
5265 if (code) {
5266 if (err && *err) {
5267 indent_msg(&err, 2);
5268 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5269 }
5270 else
5271 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5272 file, linenum, args[0], args[1], args[cur_arg]);
5273 if (code & ERR_FATAL) {
5274 free(err);
5275 cur_arg += 1 + kw->skip;
5276 goto out;
5277 }
5278 }
5279 free(err);
5280 cur_arg += 1 + kw->skip;
5281 continue;
5282 }
5283
5284 err = NULL;
5285 if (!srv_dumped) {
5286 srv_dump_kws(&err);
5287 indent_msg(&err, 4);
5288 srv_dumped = 1;
5289 }
5290
5291 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5292 file, linenum, args[0], args[1], args[cur_arg],
5293 err ? " Registered keywords :" : "", err ? err : "");
5294 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005295
Willy Tarreau93893792009-07-23 13:19:11 +02005296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
5299 }
5300
Simon Horman8c3d0be2013-11-25 10:46:40 +09005301 /* Set initial drain state using now-configured weight */
5302 set_server_drain_state(newsrv);
5303
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005305 int ret;
5306
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005307 if (newsrv->trackit) {
5308 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5309 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005312 }
5313
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005314 /* If neither a port nor an addr was specified and no check transport
5315 * layer is forced, then the transport layer used by the checks is the
5316 * same as for the production traffic. Otherwise we use raw_sock by
5317 * default, unless one is specified.
5318 */
Simon Horman66183002013-02-23 10:16:43 +09005319 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005320#ifdef USE_OPENSSL
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005321 newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
Willy Tarreau71516332012-10-10 23:01:14 +02005322#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005323 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5324 }
Simon Horman66183002013-02-23 10:16:43 +09005325 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005326 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005327 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005328
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005329 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005330 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005331
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005332 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005333 /* not yet valid, because no port was set on
5334 * the server either. We'll check if we have
5335 * a known port on the first listener.
5336 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005337 struct listener *l;
5338
5339 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005340 newsrv->check.port = get_host_port(&l->addr);
5341 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005342 break;
5343 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005344 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005345 /*
5346 * We need at least a service port, a check port or the first tcp-check rule must
5347 * be a 'connect' one
5348 */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005349 if (!newsrv->check.port) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005350 struct tcpcheck_rule *n = NULL, *r = NULL;
5351 struct list *l;
5352
5353 r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
5354 if (!r) {
5355 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5356 file, linenum, newsrv->id);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360 if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
5361 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",
5362 file, linenum, newsrv->id);
5363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
5365 }
5366 else {
5367 /* scan the tcp-check ruleset to ensure a port has been configured */
5368 l = &newsrv->proxy->tcpcheck_rules;
5369 list_for_each_entry(n, l, list) {
5370 r = (struct tcpcheck_rule *)n->list.p;
5371 if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
5372 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",
5373 file, linenum, newsrv->id);
5374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
5377 }
5378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005380
Willy Tarreau2f075e92013-12-03 11:11:34 +01005381 /* note: check type will be set during the config review phase */
5382 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005383 if (ret) {
5384 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005385 goto out;
5386 }
5387
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005388 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
5390
Simon Hormand60d6912013-11-25 10:46:36 +09005391 if (do_agent) {
5392 int ret;
5393
5394 if (!newsrv->agent.port) {
5395 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5396 file, linenum, newsrv->id);
5397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
5399 }
5400
5401 if (!newsrv->agent.inter)
5402 newsrv->agent.inter = newsrv->check.inter;
5403
5404 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5405 if (ret) {
5406 err_code |= ret;
5407 goto out;
5408 }
5409
Willy Tarreau33434322013-12-11 21:15:19 +01005410 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005411 }
5412
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005413 if (!defsrv) {
5414 if (newsrv->state & SRV_BACKUP)
5415 curproxy->srv_bck++;
5416 else
5417 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005418
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005419 newsrv->prev_state = newsrv->state;
5420 }
William Lallemanda73203e2012-03-12 12:48:57 +01005421 }
5422
5423 else if (strcmp(args[0], "unique-id-format") == 0) {
5424 if (!*(args[1])) {
5425 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
William Lallemand3203ff42012-11-11 17:30:56 +01005429 if (*(args[2])) {
5430 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005434 free(curproxy->conf.uniqueid_format_string);
5435 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005436
Willy Tarreau62a61232013-04-12 18:13:46 +02005437 free(curproxy->conf.uif_file);
5438 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5439 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005440 }
William Lallemanda73203e2012-03-12 12:48:57 +01005441
5442 else if (strcmp(args[0], "unique-id-header") == 0) {
5443 if (!*(args[1])) {
5444 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 }
5448 free(curproxy->header_unique_id);
5449 curproxy->header_unique_id = strdup(args[1]);
5450 }
5451
William Lallemand723b73a2012-02-08 16:37:49 +01005452 else if (strcmp(args[0], "log-format") == 0) {
5453 if (!*(args[1])) {
5454 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
William Lallemand3203ff42012-11-11 17:30:56 +01005458 if (*(args[2])) {
5459 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
5462 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005463
Willy Tarreau62a61232013-04-12 18:13:46 +02005464 if (curproxy->conf.logformat_string != default_http_log_format &&
5465 curproxy->conf.logformat_string != default_tcp_log_format &&
5466 curproxy->conf.logformat_string != clf_http_log_format)
5467 free(curproxy->conf.logformat_string);
5468 curproxy->conf.logformat_string = strdup(args[1]);
5469
5470 free(curproxy->conf.lfs_file);
5471 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5472 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005473
5474 /* get a chance to improve log-format error reporting by
5475 * reporting the correct line-number when possible.
5476 */
5477 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5478 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5479 file, linenum, curproxy->id);
5480 err_code |= ERR_WARN;
5481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 }
William Lallemand723b73a2012-02-08 16:37:49 +01005483
William Lallemand0f99e342011-10-12 17:50:54 +02005484 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5485 /* delete previous herited or defined syslog servers */
5486 struct logsrv *back;
5487
5488 if (*(args[1]) != 0) {
5489 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
5493
William Lallemand723b73a2012-02-08 16:37:49 +01005494 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5495 LIST_DEL(&tmplogsrv->list);
5496 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005497 }
5498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005500 struct logsrv *logsrv;
5501
Willy Tarreaubaaee002006-06-26 02:48:02 +02005502 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005503 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005504 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005505 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005506 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005507 LIST_INIT(&node->list);
5508 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
5511 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005512 struct sockaddr_storage *sk;
5513 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005514
5515 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516
William Lallemand0f99e342011-10-12 17:50:54 +02005517 logsrv->facility = get_log_facility(args[2]);
5518 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
5524
William Lallemand0f99e342011-10-12 17:50:54 +02005525 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005526 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005527 logsrv->level = get_log_level(args[3]);
5528 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005530 err_code |= ERR_ALERT | ERR_FATAL;
5531 goto out;
5532
Willy Tarreaubaaee002006-06-26 02:48:02 +02005533 }
5534 }
5535
William Lallemand0f99e342011-10-12 17:50:54 +02005536 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005537 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005538 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005539 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005540 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005544 }
5545 }
5546
Willy Tarreau902636f2013-03-10 19:44:48 +01005547 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005548 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005549 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005550 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005551 goto out;
5552 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005553
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005554 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005555
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005556 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005557 if (port1 != port2) {
5558 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5559 file, linenum, args[0], args[1]);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005564 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005565 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 }
William Lallemand0f99e342011-10-12 17:50:54 +02005567
5568 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 }
5570 else {
5571 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5572 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 }
5576 }
5577 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005578 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005579 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005580 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005581 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005582
Willy Tarreau977b8e42006-12-29 14:19:17 +01005583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005585
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005587 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5588 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005592
5593 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005594 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5595 free(curproxy->conn_src.iface_name);
5596 curproxy->conn_src.iface_name = NULL;
5597 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005598
Willy Tarreau902636f2013-03-10 19:44:48 +01005599 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005600 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005601 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005602 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005603 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005604 goto out;
5605 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005606
5607 proto = protocol_by_family(sk->ss_family);
5608 if (!proto || !proto->connect) {
5609 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005610 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005614
5615 if (port1 != port2) {
5616 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5617 file, linenum, args[0], args[1]);
5618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
5621
Willy Tarreauef9a3602012-12-08 22:29:20 +01005622 curproxy->conn_src.source_addr = *sk;
5623 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005624
5625 cur_arg = 2;
5626 while (*(args[cur_arg])) {
5627 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005628#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5629#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005630 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005631 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5632 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005635 }
5636#endif
5637 if (!*args[cur_arg + 1]) {
5638 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5639 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005642 }
5643
5644 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005645 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5646 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005647 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005648 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5649 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005650 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5651 char *name, *end;
5652
5653 name = args[cur_arg+1] + 7;
5654 while (isspace(*name))
5655 name++;
5656
5657 end = name;
5658 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5659 end++;
5660
Willy Tarreauef9a3602012-12-08 22:29:20 +01005661 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5662 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5663 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5664 curproxy->conn_src.bind_hdr_len = end - name;
5665 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5666 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5667 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005668
5669 /* now look for an occurrence number */
5670 while (isspace(*end))
5671 end++;
5672 if (*end == ',') {
5673 end++;
5674 name = end;
5675 if (*end == '-')
5676 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005677 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005678 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005679 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005680 }
5681
Willy Tarreauef9a3602012-12-08 22:29:20 +01005682 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005683 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5684 " occurrences values smaller than %d.\n",
5685 file, linenum, MAX_HDR_HISTORY);
5686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
5688 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005689 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005690 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005691
Willy Tarreau902636f2013-03-10 19:44:48 +01005692 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005693 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005694 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005695 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005696 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005697 goto out;
5698 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005699
5700 proto = protocol_by_family(sk->ss_family);
5701 if (!proto || !proto->connect) {
5702 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5703 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
5706 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005707
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005708 if (port1 != port2) {
5709 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5710 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
5713 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005714 curproxy->conn_src.tproxy_addr = *sk;
5715 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005716 }
5717 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005718#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005719 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005720#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005721#else /* no TPROXY support */
5722 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005723 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005726#endif
5727 cur_arg += 2;
5728 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005729 }
5730
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005731 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5732#ifdef SO_BINDTODEVICE
5733 if (!*args[cur_arg + 1]) {
5734 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5735 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005738 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005739 free(curproxy->conn_src.iface_name);
5740 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5741 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005742 global.last_checks |= LSTCHK_NETADM;
5743#else
5744 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5745 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005748#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005749 cur_arg += 2;
5750 continue;
5751 }
5752 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005753 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
5755 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005758 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5759 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5760 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005765 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005771
5772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005773 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005774 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005775 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
5778 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005780 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005781 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005782 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
5785 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005787 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005788 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
5792 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005794 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005795 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
5799 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005801 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005802 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005803 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005806 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005807 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005808 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005809 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005810 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005811 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005812 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005813 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005814 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005815 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005816 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005817 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005818 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005819 }
5820 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005822 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005823 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005825 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005828 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5830 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005831 err_code |= ERR_ALERT | ERR_FATAL;
5832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005834
5835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005836 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005837 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005838 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 }
5841 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005843 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005844 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005845 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 }
5848 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005849 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005850 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005851 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005852 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 }
5855 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005856 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005857 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005858 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005859 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861 }
5862 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005863 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005864 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005865 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005866 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005869 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005870 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005871 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005872 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005873 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005874 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005877 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005878
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879 if (curproxy == &defproxy) {
5880 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005884 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 if (*(args[1]) == 0) {
5888 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005889 err_code |= ERR_ALERT | ERR_FATAL;
5890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005892
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005893 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005894 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5895 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5896 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005900 err_code |= warnif_cond_conflicts(cond,
5901 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5902 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005903 }
5904 else if (*args[2]) {
5905 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5906 file, linenum, args[0], args[2]);
5907 err_code |= ERR_ALERT | ERR_FATAL;
5908 goto out;
5909 }
5910
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005911 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005912 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005913 wl->s = strdup(args[1]);
5914 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005915 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 }
5917 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005918 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005921 err_code |= ERR_ALERT | ERR_FATAL;
5922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005924
Willy Tarreauade5ec42010-01-28 19:33:49 +01005925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005926 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005927 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 }
5931 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005933 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005934 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 }
5938 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005940 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 }
5945 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005946 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005949 err_code |= ERR_ALERT | ERR_FATAL;
5950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951 }
5952
Willy Tarreauade5ec42010-01-28 19:33:49 +01005953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005954 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005955 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 }
5959 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005961 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005962 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005965 }
5966 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005968 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972 }
5973 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005974 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005975
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976 if (curproxy == &defproxy) {
5977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005978 err_code |= ERR_ALERT | ERR_FATAL;
5979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005981 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005982 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 if (*(args[1]) == 0) {
5985 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005986 err_code |= ERR_ALERT | ERR_FATAL;
5987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 }
5989
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005990 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5992 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5993 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005994 err_code |= ERR_ALERT | ERR_FATAL;
5995 goto out;
5996 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005997 err_code |= warnif_cond_conflicts(cond,
5998 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5999 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006000 }
6001 else if (*args[2]) {
6002 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6003 file, linenum, args[0], args[2]);
6004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
6006 }
6007
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006008 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006009 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006010 wl->s = strdup(args[1]);
6011 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 }
6013 else if (!strcmp(args[0], "errorloc") ||
6014 !strcmp(args[0], "errorloc302") ||
6015 !strcmp(args[0], "errorloc303")) { /* error location */
6016 int errnum, errlen;
6017 char *err;
6018
Willy Tarreau977b8e42006-12-29 14:19:17 +01006019 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006020 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006021
Willy Tarreaubaaee002006-06-26 02:48:02 +02006022 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006023 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 }
6027
6028 errnum = atol(args[1]);
6029 if (!strcmp(args[0], "errorloc303")) {
6030 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
6031 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
6032 } else {
6033 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
6034 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
6035 }
6036
Willy Tarreau0f772532006-12-23 20:51:41 +01006037 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6038 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006039 chunk_destroy(&curproxy->errmsg[rc]);
6040 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006041 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006044
6045 if (rc >= HTTP_ERR_SIZE) {
6046 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6047 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 free(err);
6049 }
6050 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006051 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6052 int errnum, errlen, fd;
6053 char *err;
6054 struct stat stat;
6055
6056 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006057 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006058
6059 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006060 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006061 err_code |= ERR_ALERT | ERR_FATAL;
6062 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006063 }
6064
6065 fd = open(args[2], O_RDONLY);
6066 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6067 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6068 file, linenum, args[2], args[1]);
6069 if (fd >= 0)
6070 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006071 err_code |= ERR_ALERT | ERR_FATAL;
6072 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006073 }
6074
Willy Tarreau27a674e2009-08-17 07:23:33 +02006075 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006076 errlen = stat.st_size;
6077 } else {
6078 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006079 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006080 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006081 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006082 }
6083
6084 err = malloc(errlen); /* malloc() must succeed during parsing */
6085 errnum = read(fd, err, errlen);
6086 if (errnum != errlen) {
6087 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6088 file, linenum, args[2], args[1]);
6089 close(fd);
6090 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006091 err_code |= ERR_ALERT | ERR_FATAL;
6092 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006093 }
6094 close(fd);
6095
6096 errnum = atol(args[1]);
6097 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6098 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006099 chunk_destroy(&curproxy->errmsg[rc]);
6100 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006101 break;
6102 }
6103 }
6104
6105 if (rc >= HTTP_ERR_SIZE) {
6106 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6107 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006108 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006109 free(err);
6110 }
6111 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006112 else if (!strcmp(args[0], "compression")) {
6113 struct comp *comp;
6114 if (curproxy->comp == NULL) {
6115 comp = calloc(1, sizeof(struct comp));
6116 curproxy->comp = comp;
6117 } else {
6118 comp = curproxy->comp;
6119 }
6120
6121 if (!strcmp(args[1], "algo")) {
6122 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006123 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006124
William Lallemand82fe75c2012-10-23 10:25:10 +02006125 cur_arg = 2;
6126 if (!*args[cur_arg]) {
6127 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6128 file, linenum, args[0]);
6129 err_code |= ERR_ALERT | ERR_FATAL;
6130 goto out;
6131 }
6132 while (*(args[cur_arg])) {
6133 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6134 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6135 file, linenum, args[0], args[cur_arg]);
6136 err_code |= ERR_ALERT | ERR_FATAL;
6137 goto out;
6138 }
William Lallemand552df672012-11-07 13:21:47 +01006139 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6140 curproxy->comp->algos->end(&ctx);
6141 } else {
6142 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6143 file, linenum, args[0], args[cur_arg]);
6144 err_code |= ERR_ALERT | ERR_FATAL;
6145 goto out;
6146 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006147 cur_arg ++;
6148 continue;
6149 }
6150 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006151 else if (!strcmp(args[1], "offload")) {
6152 comp->offload = 1;
6153 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006154 else if (!strcmp(args[1], "type")) {
6155 int cur_arg;
6156 cur_arg = 2;
6157 if (!*args[cur_arg]) {
6158 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6159 file, linenum, args[0]);
6160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
6162 }
6163 while (*(args[cur_arg])) {
6164 comp_append_type(comp, args[cur_arg]);
6165 cur_arg ++;
6166 continue;
6167 }
6168 }
6169 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006170 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006171 file, linenum, args[0]);
6172 err_code |= ERR_ALERT | ERR_FATAL;
6173 goto out;
6174 }
6175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006177 struct cfg_kw_list *kwl;
6178 int index;
6179
6180 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6181 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6182 if (kwl->kw[index].section != CFG_LISTEN)
6183 continue;
6184 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6185 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006186 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006187 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006188 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006189 err_code |= ERR_ALERT | ERR_FATAL;
6190 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006191 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006192 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006193 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006194 err_code |= ERR_WARN;
6195 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006196 }
Willy Tarreau93893792009-07-23 13:19:11 +02006197 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006198 }
6199 }
6200 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006201
Willy Tarreau6daf3432008-01-22 16:44:08 +01006202 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006203 err_code |= ERR_ALERT | ERR_FATAL;
6204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 }
Willy Tarreau93893792009-07-23 13:19:11 +02006206 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006207 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006208 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209}
6210
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006211int
6212cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6213{
6214
6215 int err_code = 0;
6216 const char *err;
6217
6218 if (!strcmp(args[0], "userlist")) { /* new userlist */
6219 struct userlist *newul;
6220
6221 if (!*args[1]) {
6222 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6223 file, linenum, args[0]);
6224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
6226 }
6227
6228 err = invalid_char(args[1]);
6229 if (err) {
6230 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6231 file, linenum, *err, args[0], args[1]);
6232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234 }
6235
6236 for (newul = userlist; newul; newul = newul->next)
6237 if (!strcmp(newul->name, args[1])) {
6238 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6239 file, linenum, args[1]);
6240 err_code |= ERR_WARN;
6241 goto out;
6242 }
6243
6244 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6245 if (!newul) {
6246 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6247 err_code |= ERR_ALERT | ERR_ABORT;
6248 goto out;
6249 }
6250
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006251 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006252 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006253 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6254 err_code |= ERR_ALERT | ERR_ABORT;
6255 goto out;
6256 }
6257
6258 newul->next = userlist;
6259 userlist = newul;
6260
6261 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006262 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006263 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006264 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006265
6266 if (!*args[1]) {
6267 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6268 file, linenum, args[0]);
6269 err_code |= ERR_ALERT | ERR_FATAL;
6270 goto out;
6271 }
6272
6273 err = invalid_char(args[1]);
6274 if (err) {
6275 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6276 file, linenum, *err, args[0], args[1]);
6277 err_code |= ERR_ALERT | ERR_FATAL;
6278 goto out;
6279 }
6280
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006281 for (ag = userlist->groups; ag; ag = ag->next)
6282 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006283 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6284 file, linenum, args[1], userlist->name);
6285 err_code |= ERR_ALERT;
6286 goto out;
6287 }
6288
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006289 ag = calloc(1, sizeof(*ag));
6290 if (!ag) {
6291 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6292 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006293 goto out;
6294 }
6295
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006296 ag->name = strdup(args[1]);
6297 if (!ag) {
6298 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6299 err_code |= ERR_ALERT | ERR_ABORT;
6300 goto out;
6301 }
6302
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006303 cur_arg = 2;
6304
6305 while (*args[cur_arg]) {
6306 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006307 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006308 cur_arg += 2;
6309 continue;
6310 } else {
6311 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6312 file, linenum, args[0]);
6313 err_code |= ERR_ALERT | ERR_FATAL;
6314 goto out;
6315 }
6316 }
6317
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006318 ag->next = userlist->groups;
6319 userlist->groups = ag;
6320
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006321 } else if (!strcmp(args[0], "user")) { /* new user */
6322 struct auth_users *newuser;
6323 int cur_arg;
6324
6325 if (!*args[1]) {
6326 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6327 file, linenum, args[0]);
6328 err_code |= ERR_ALERT | ERR_FATAL;
6329 goto out;
6330 }
6331
6332 for (newuser = userlist->users; newuser; newuser = newuser->next)
6333 if (!strcmp(newuser->user, args[1])) {
6334 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6335 file, linenum, args[1], userlist->name);
6336 err_code |= ERR_ALERT;
6337 goto out;
6338 }
6339
6340 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6341 if (!newuser) {
6342 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6343 err_code |= ERR_ALERT | ERR_ABORT;
6344 goto out;
6345 }
6346
6347 newuser->user = strdup(args[1]);
6348
6349 newuser->next = userlist->users;
6350 userlist->users = newuser;
6351
6352 cur_arg = 2;
6353
6354 while (*args[cur_arg]) {
6355 if (!strcmp(args[cur_arg], "password")) {
6356#ifndef CONFIG_HAP_CRYPT
6357 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6358 file, linenum);
6359 err_code |= ERR_ALERT;
6360#endif
6361 newuser->pass = strdup(args[cur_arg + 1]);
6362 cur_arg += 2;
6363 continue;
6364 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6365 newuser->pass = strdup(args[cur_arg + 1]);
6366 newuser->flags |= AU_O_INSECURE;
6367 cur_arg += 2;
6368 continue;
6369 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006370 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006371 cur_arg += 2;
6372 continue;
6373 } else {
6374 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6375 file, linenum, args[0]);
6376 err_code |= ERR_ALERT | ERR_FATAL;
6377 goto out;
6378 }
6379 }
6380 } else {
6381 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6382 err_code |= ERR_ALERT | ERR_FATAL;
6383 }
6384
6385out:
6386 return err_code;
6387}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388
6389/*
6390 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006391 * Returns the error code, 0 if OK, or any combination of :
6392 * - ERR_ABORT: must abort ASAP
6393 * - ERR_FATAL: we can continue parsing but not start the service
6394 * - ERR_WARN: a warning has been emitted
6395 * - ERR_ALERT: an alert has been emitted
6396 * Only the two first ones can stop processing, the two others are just
6397 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006399int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006400{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006401 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 FILE *f;
6403 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006404 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006405 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406
Willy Tarreaubaaee002006-06-26 02:48:02 +02006407 if ((f=fopen(file,"r")) == NULL)
6408 return -1;
6409
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006410 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006411 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006412 char *end;
6413 char *args[MAX_LINE_ARGS + 1];
6414 char *line = thisline;
6415
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 linenum++;
6417
6418 end = line + strlen(line);
6419
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006420 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6421 /* Check if we reached the limit and the last char is not \n.
6422 * Watch out for the last line without the terminating '\n'!
6423 */
6424 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006425 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006426 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006427 }
6428
Willy Tarreaubaaee002006-06-26 02:48:02 +02006429 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006430 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431 line++;
6432
6433 arg = 0;
6434 args[arg] = line;
6435
6436 while (*line && arg < MAX_LINE_ARGS) {
6437 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6438 * C equivalent value. Other combinations left unchanged (eg: \1).
6439 */
6440 if (*line == '\\') {
6441 int skip = 0;
6442 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6443 *line = line[1];
6444 skip = 1;
6445 }
6446 else if (line[1] == 'r') {
6447 *line = '\r';
6448 skip = 1;
6449 }
6450 else if (line[1] == 'n') {
6451 *line = '\n';
6452 skip = 1;
6453 }
6454 else if (line[1] == 't') {
6455 *line = '\t';
6456 skip = 1;
6457 }
6458 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006459 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 unsigned char hex1, hex2;
6461 hex1 = toupper(line[2]) - '0';
6462 hex2 = toupper(line[3]) - '0';
6463 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6464 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6465 *line = (hex1<<4) + hex2;
6466 skip = 3;
6467 }
6468 else {
6469 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006470 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471 }
6472 }
6473 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006474 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 end -= skip;
6476 }
6477 line++;
6478 }
6479 else if (*line == '#' || *line == '\n' || *line == '\r') {
6480 /* end of string, end of loop */
6481 *line = 0;
6482 break;
6483 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006484 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006486 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006487 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006488 line++;
6489 args[++arg] = line;
6490 }
6491 else {
6492 line++;
6493 }
6494 }
6495
6496 /* empty line */
6497 if (!**args)
6498 continue;
6499
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006500 if (*line) {
6501 /* we had to stop due to too many args.
6502 * Let's terminate the string, print the offending part then cut the
6503 * last arg.
6504 */
6505 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6506 line++;
6507 *line = '\0';
6508
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006509 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006510 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006511 err_code |= ERR_ALERT | ERR_FATAL;
6512 args[arg] = line;
6513 }
6514
Willy Tarreau540abe42007-05-02 20:50:16 +02006515 /* zero out remaining args and ensure that at least one entry
6516 * is zeroed out.
6517 */
6518 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 args[arg] = line;
6520 }
6521
Willy Tarreau3842f002009-06-14 11:39:52 +02006522 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006523 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006524 char *tmp;
6525
Willy Tarreau3842f002009-06-14 11:39:52 +02006526 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006527 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006528 for (arg=0; *args[arg+1]; arg++)
6529 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006530 *tmp = '\0'; // fix the next arg to \0
6531 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006532 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006533 else if (!strcmp(args[0], "default")) {
6534 kwm = KWM_DEF;
6535 for (arg=0; *args[arg+1]; arg++)
6536 args[arg] = args[arg+1]; // shift args after inversion
6537 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006538
William Lallemand0f99e342011-10-12 17:50:54 +02006539 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6540 strcmp(args[0], "log") != 0) {
6541 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006542 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006543 }
6544
Willy Tarreau977b8e42006-12-29 14:19:17 +01006545 if (!strcmp(args[0], "listen") ||
6546 !strcmp(args[0], "frontend") ||
6547 !strcmp(args[0], "backend") ||
6548 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006549 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006551 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006552 cursection = strdup(args[0]);
6553 }
6554 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006556 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006557 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006558 }
6559 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006560 confsect = CFG_USERLIST;
6561 free(cursection);
6562 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006563 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006564 else if (!strcmp(args[0], "peers")) {
6565 confsect = CFG_PEERS;
6566 free(cursection);
6567 cursection = strdup(args[0]);
6568 }
6569
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 /* else it's a section keyword */
6571
6572 switch (confsect) {
6573 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006574 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006575 break;
6576 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006577 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006578 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006579 case CFG_USERLIST:
6580 err_code |= cfg_parse_users(file, linenum, args, kwm);
6581 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006582 case CFG_PEERS:
6583 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6584 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006585 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006586 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006587 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006589
6590 if (err_code & ERR_ABORT)
6591 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006592 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006593 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006594 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006596 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006597}
6598
Willy Tarreaubb925012009-07-23 13:36:36 +02006599/*
6600 * Returns the error code, 0 if OK, or any combination of :
6601 * - ERR_ABORT: must abort ASAP
6602 * - ERR_FATAL: we can continue parsing but not start the service
6603 * - ERR_WARN: a warning has been emitted
6604 * - ERR_ALERT: an alert has been emitted
6605 * Only the two first ones can stop processing, the two others are just
6606 * indicators.
6607 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006608int check_config_validity()
6609{
6610 int cfgerr = 0;
6611 struct proxy *curproxy = NULL;
6612 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006613 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006614 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006615 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006617 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006618 /*
6619 * Now, check for the integrity of all that we have collected.
6620 */
6621
6622 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006623 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006624
Willy Tarreau193b8c62012-11-22 00:17:38 +01006625 if (!global.tune.max_http_hdr)
6626 global.tune.max_http_hdr = MAX_HTTP_HDR;
6627
6628 if (!global.tune.cookie_len)
6629 global.tune.cookie_len = CAPTURE_LEN;
6630
6631 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6632
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006633 /* Post initialisation of the users and groups lists. */
6634 err_code = userlist_postinit();
6635 if (err_code != ERR_NONE)
6636 goto out;
6637
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006638 /* first, we will invert the proxy list order */
6639 curproxy = NULL;
6640 while (proxy) {
6641 struct proxy *next;
6642
6643 next = proxy->next;
6644 proxy->next = curproxy;
6645 curproxy = proxy;
6646 if (!next)
6647 break;
6648 proxy = next;
6649 }
6650
Willy Tarreaubaaee002006-06-26 02:48:02 +02006651 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006652 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006653 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006654 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006655 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006656 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006657 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006658 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006659
Willy Tarreau050536d2012-10-04 08:47:34 +02006660 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006661 /* proxy ID not set, use automatic numbering with first
6662 * spare entry starting with next_pxid.
6663 */
6664 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6665 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6666 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006667 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006668 next_pxid++;
6669
Willy Tarreau55ea7572007-06-17 19:56:27 +02006670
Willy Tarreaubaaee002006-06-26 02:48:02 +02006671 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006672 /* ensure we don't keep listeners uselessly bound */
6673 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006674 curproxy = curproxy->next;
6675 continue;
6676 }
6677
Willy Tarreau16a21472012-11-19 12:39:59 +01006678 /* number of processes this proxy is bound to */
6679 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6680
Willy Tarreauff01a212009-03-15 13:46:16 +01006681 switch (curproxy->mode) {
6682 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006683 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006684 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006685 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6686 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006687 cfgerr++;
6688 }
6689
6690 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006691 Warning("config : servers will be ignored for %s '%s'.\n",
6692 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006693 break;
6694
6695 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006696 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006697 break;
6698
6699 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006700 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006701 break;
6702 }
6703
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006704 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006705 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006706 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006707 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6708 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006709 cfgerr++;
6710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006711#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006712 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006713 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6714 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006715 cfgerr++;
6716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006717#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006718 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006719 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6720 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006721 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006722 }
6723 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006724 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006725 /* If no LB algo is set in a backend, and we're not in
6726 * transparent mode, dispatch mode nor proxy mode, we
6727 * want to use balance roundrobin by default.
6728 */
6729 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6730 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006731 }
6732 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006733
Willy Tarreau1620ec32011-08-06 17:05:02 +02006734 if (curproxy->options & PR_O_DISPATCH)
6735 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6736 else if (curproxy->options & PR_O_HTTP_PROXY)
6737 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6738 else if (curproxy->options & PR_O_TRANSP)
6739 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006740
Willy Tarreau1620ec32011-08-06 17:05:02 +02006741 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6742 if (curproxy->options & PR_O_DISABLE404) {
6743 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6744 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6745 err_code |= ERR_WARN;
6746 curproxy->options &= ~PR_O_DISABLE404;
6747 }
6748 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6749 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6750 "send-state", proxy_type_str(curproxy), curproxy->id);
6751 err_code |= ERR_WARN;
6752 curproxy->options &= ~PR_O2_CHK_SNDST;
6753 }
Willy Tarreauef781042010-01-27 11:53:01 +01006754 }
6755
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006756 /* if a default backend was specified, let's find it */
6757 if (curproxy->defbe.name) {
6758 struct proxy *target;
6759
Alex Williams96532db2009-11-01 21:27:13 -05006760 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006761 if (!target) {
6762 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6763 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006764 cfgerr++;
6765 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006766 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6767 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006768 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006769 } else {
6770 free(curproxy->defbe.name);
6771 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006772 /* we force the backend to be present on at least all of
6773 * the frontend's processes.
6774 */
6775 target->bind_proc = curproxy->bind_proc ?
6776 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006777
6778 /* Emit a warning if this proxy also has some servers */
6779 if (curproxy->srv) {
6780 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6781 curproxy->id);
6782 err_code |= ERR_WARN;
6783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006784 }
6785 }
6786
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006787 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006788 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6789 /* map jump target for ACT_SETBE in req_rep chain */
6790 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006791 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006792 struct proxy *target;
6793
Willy Tarreaua496b602006-12-17 23:15:24 +01006794 if (exp->action != ACT_SETBE)
6795 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006796
Alex Williams96532db2009-11-01 21:27:13 -05006797 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006798 if (!target) {
6799 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6800 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006801 cfgerr++;
6802 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006803 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6804 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006805 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006806 } else {
6807 free((void *)exp->replace);
6808 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006809 /* we force the backend to be present on at least all of
6810 * the frontend's processes.
6811 */
6812 target->bind_proc = curproxy->bind_proc ?
6813 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006814 }
6815 }
6816 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006817
6818 /* find the target proxy for 'use_backend' rules */
6819 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006820 struct proxy *target;
6821
Alex Williams96532db2009-11-01 21:27:13 -05006822 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006823
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006824 if (!target) {
6825 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6826 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006827 cfgerr++;
6828 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006829 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6830 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006831 cfgerr++;
6832 } else {
6833 free((void *)rule->be.name);
6834 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006835 /* we force the backend to be present on at least all of
6836 * the frontend's processes.
6837 */
6838 target->bind_proc = curproxy->bind_proc ?
6839 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006840 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006841 }
6842
6843 /* find the target proxy for 'use_backend' rules */
6844 list_for_each_entry(srule, &curproxy->server_rules, list) {
6845 struct server *target = findserver(curproxy, srule->srv.name);
6846
6847 if (!target) {
6848 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6849 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6850 cfgerr++;
6851 continue;
6852 }
6853 free((void *)srule->srv.name);
6854 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006855 }
6856
Emeric Brunb982a3d2010-01-04 15:45:53 +01006857 /* find the target table for 'stick' rules */
6858 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6859 struct proxy *target;
6860
Emeric Brun1d33b292010-01-04 15:47:17 +01006861 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6862 if (mrule->flags & STK_IS_STORE)
6863 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6864
Emeric Brunb982a3d2010-01-04 15:45:53 +01006865 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006866 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006867 else
6868 target = curproxy;
6869
6870 if (!target) {
6871 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6872 curproxy->id, mrule->table.name);
6873 cfgerr++;
6874 }
6875 else if (target->table.size == 0) {
6876 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6877 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6878 cfgerr++;
6879 }
Willy Tarreau12785782012-04-27 21:37:17 +02006880 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6881 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006882 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6883 cfgerr++;
6884 }
6885 else {
6886 free((void *)mrule->table.name);
6887 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006888 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006889 }
6890 }
6891
6892 /* find the target table for 'store response' rules */
6893 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6894 struct proxy *target;
6895
Emeric Brun1d33b292010-01-04 15:47:17 +01006896 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6897
Emeric Brunb982a3d2010-01-04 15:45:53 +01006898 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006899 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006900 else
6901 target = curproxy;
6902
6903 if (!target) {
6904 Alert("Proxy '%s': unable to find store table '%s'.\n",
6905 curproxy->id, mrule->table.name);
6906 cfgerr++;
6907 }
6908 else if (target->table.size == 0) {
6909 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6910 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6911 cfgerr++;
6912 }
Willy Tarreau12785782012-04-27 21:37:17 +02006913 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6914 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006915 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6916 cfgerr++;
6917 }
6918 else {
6919 free((void *)mrule->table.name);
6920 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006921 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006922 }
6923 }
6924
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006925 /* find the target table for 'tcp-request' layer 4 rules */
6926 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6927 struct proxy *target;
6928
Willy Tarreaub4c84932013-07-23 19:15:30 +02006929 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006930 continue;
6931
6932 if (trule->act_prm.trk_ctr.table.n)
6933 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6934 else
6935 target = curproxy;
6936
6937 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006938 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6939 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006940 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006941 cfgerr++;
6942 }
6943 else if (target->table.size == 0) {
6944 Alert("Proxy '%s': table '%s' used but not configured.\n",
6945 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6946 cfgerr++;
6947 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006948 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6949 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6950 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 +01006951 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006952 cfgerr++;
6953 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006954 else {
6955 free(trule->act_prm.trk_ctr.table.n);
6956 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006957 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006958 * to pass a list of counters to track and allocate them right here using
6959 * stktable_alloc_data_type().
6960 */
6961 }
6962 }
6963
Willy Tarreaud1f96522010-08-03 19:34:32 +02006964 /* find the target table for 'tcp-request' layer 6 rules */
6965 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6966 struct proxy *target;
6967
Willy Tarreaub4c84932013-07-23 19:15:30 +02006968 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006969 continue;
6970
6971 if (trule->act_prm.trk_ctr.table.n)
6972 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6973 else
6974 target = curproxy;
6975
6976 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006977 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6978 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006979 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006980 cfgerr++;
6981 }
6982 else if (target->table.size == 0) {
6983 Alert("Proxy '%s': table '%s' used but not configured.\n",
6984 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6985 cfgerr++;
6986 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006987 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6988 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6989 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 +01006990 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006991 cfgerr++;
6992 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006993 else {
6994 free(trule->act_prm.trk_ctr.table.n);
6995 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006996 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006997 * to pass a list of counters to track and allocate them right here using
6998 * stktable_alloc_data_type().
6999 */
7000 }
7001 }
7002
Emeric Brun32da3c42010-09-23 18:39:19 +02007003 if (curproxy->table.peers.name) {
7004 struct peers *curpeers = peers;
7005
7006 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7007 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7008 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007009 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007010 break;
7011 }
7012 }
7013
7014 if (!curpeers) {
7015 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7016 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007017 free((void *)curproxy->table.peers.name);
7018 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007019 cfgerr++;
7020 }
7021 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007022 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7023 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007024 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007025 cfgerr++;
7026 }
7027 }
7028
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007029 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007030 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007031 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7032 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7033 "proxy", curproxy->id);
7034 cfgerr++;
7035 goto out_uri_auth_compat;
7036 }
7037
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007038 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007039 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007040 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007041 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007042
Willy Tarreau95fa4692010-02-01 13:05:50 +01007043 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7044 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007045
7046 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007047 uri_auth_compat_req[i++] = "realm";
7048 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7049 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007050
Willy Tarreau95fa4692010-02-01 13:05:50 +01007051 uri_auth_compat_req[i++] = "unless";
7052 uri_auth_compat_req[i++] = "{";
7053 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7054 uri_auth_compat_req[i++] = "}";
7055 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007056
Willy Tarreauff011f22011-01-06 17:51:27 +01007057 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7058 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007059 cfgerr++;
7060 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007061 }
7062
Willy Tarreauff011f22011-01-06 17:51:27 +01007063 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007064
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007065 if (curproxy->uri_auth->auth_realm) {
7066 free(curproxy->uri_auth->auth_realm);
7067 curproxy->uri_auth->auth_realm = NULL;
7068 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007069
7070 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007071 }
7072out_uri_auth_compat:
7073
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007074 /* compile the log format */
7075 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007076 if (curproxy->conf.logformat_string != default_http_log_format &&
7077 curproxy->conf.logformat_string != default_tcp_log_format &&
7078 curproxy->conf.logformat_string != clf_http_log_format)
7079 free(curproxy->conf.logformat_string);
7080 curproxy->conf.logformat_string = NULL;
7081 free(curproxy->conf.lfs_file);
7082 curproxy->conf.lfs_file = NULL;
7083 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007084 }
7085
Willy Tarreau62a61232013-04-12 18:13:46 +02007086 if (curproxy->conf.logformat_string) {
7087 curproxy->conf.args.ctx = ARGC_LOG;
7088 curproxy->conf.args.file = curproxy->conf.lfs_file;
7089 curproxy->conf.args.line = curproxy->conf.lfs_line;
7090 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007091 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007092 curproxy->conf.args.file = NULL;
7093 curproxy->conf.args.line = 0;
7094 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007095
Willy Tarreau62a61232013-04-12 18:13:46 +02007096 if (curproxy->conf.uniqueid_format_string) {
7097 curproxy->conf.args.ctx = ARGC_UIF;
7098 curproxy->conf.args.file = curproxy->conf.uif_file;
7099 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007100 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007101 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
7102 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007103 curproxy->conf.args.file = NULL;
7104 curproxy->conf.args.line = 0;
7105 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007106
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007107 /* only now we can check if some args remain unresolved.
7108 * This must be done after the users and groups resolution.
7109 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007110 cfgerr += smp_resolve_args(curproxy);
7111 if (!cfgerr)
7112 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007113
Willy Tarreau2738a142006-07-08 17:28:09 +02007114 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007115 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007116 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007117 (!curproxy->timeout.connect ||
7118 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007119 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007120 " | While not properly invalid, you will certainly encounter various problems\n"
7121 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007122 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007123 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007124 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007125 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007126
Willy Tarreau1fa31262007-12-03 00:36:16 +01007127 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7128 * We must still support older configurations, so let's find out whether those
7129 * parameters have been set or must be copied from contimeouts.
7130 */
7131 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007132 if (!curproxy->timeout.tarpit ||
7133 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007134 /* tarpit timeout not set. We search in the following order:
7135 * default.tarpit, curr.connect, default.connect.
7136 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007137 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007138 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007139 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007140 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007141 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007142 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007143 }
7144 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007145 (!curproxy->timeout.queue ||
7146 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007147 /* queue timeout not set. We search in the following order:
7148 * default.queue, curr.connect, default.connect.
7149 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007150 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007151 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007152 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007153 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007154 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007155 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007156 }
7157 }
7158
Willy Tarreau1620ec32011-08-06 17:05:02 +02007159 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007160 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7161 curproxy->check_req = (char *)malloc(curproxy->check_len);
7162 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007163 }
7164
Willy Tarreau193b8c62012-11-22 00:17:38 +01007165 /* ensure that cookie capture length is not too large */
7166 if (curproxy->capture_len >= global.tune.cookie_len) {
7167 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7168 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7169 err_code |= ERR_WARN;
7170 curproxy->capture_len = global.tune.cookie_len - 1;
7171 }
7172
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007173 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007174 if (curproxy->nb_req_cap) {
7175 if (curproxy->mode == PR_MODE_HTTP) {
7176 curproxy->req_cap_pool = create_pool("ptrcap",
7177 curproxy->nb_req_cap * sizeof(char *),
7178 MEM_F_SHARED);
7179 } else {
7180 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7181 proxy_type_str(curproxy), curproxy->id);
7182 err_code |= ERR_WARN;
7183 curproxy->to_log &= ~LW_REQHDR;
7184 curproxy->nb_req_cap = 0;
7185 }
7186 }
7187
7188 if (curproxy->nb_rsp_cap) {
7189 if (curproxy->mode == PR_MODE_HTTP) {
7190 curproxy->rsp_cap_pool = create_pool("ptrcap",
7191 curproxy->nb_rsp_cap * sizeof(char *),
7192 MEM_F_SHARED);
7193 } else {
7194 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7195 proxy_type_str(curproxy), curproxy->id);
7196 err_code |= ERR_WARN;
7197 curproxy->to_log &= ~LW_REQHDR;
7198 curproxy->nb_rsp_cap = 0;
7199 }
7200 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007201
Willy Tarreaubaaee002006-06-26 02:48:02 +02007202 /* first, we will invert the servers list order */
7203 newsrv = NULL;
7204 while (curproxy->srv) {
7205 struct server *next;
7206
7207 next = curproxy->srv->next;
7208 curproxy->srv->next = newsrv;
7209 newsrv = curproxy->srv;
7210 if (!next)
7211 break;
7212 curproxy->srv = next;
7213 }
7214
Willy Tarreau17edc812014-01-03 12:14:34 +01007215 /* Check that no server name conflicts. This causes trouble in the stats.
7216 * We only emit a warning for the first conflict affecting each server,
7217 * in order to avoid combinatory explosion if all servers have the same
7218 * name. We do that only for servers which do not have an explicit ID,
7219 * because these IDs were made also for distinguishing them and we don't
7220 * want to annoy people who correctly manage them.
7221 */
7222 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7223 struct server *other_srv;
7224
7225 if (newsrv->puid)
7226 continue;
7227
7228 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7229 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7230 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7231 newsrv->conf.file, newsrv->conf.line,
7232 proxy_type_str(curproxy), curproxy->id,
7233 newsrv->id, other_srv->conf.line);
7234 break;
7235 }
7236 }
7237 }
7238
Willy Tarreaudd701652010-05-25 23:03:02 +02007239 /* assign automatic UIDs to servers which don't have one yet */
7240 next_id = 1;
7241 newsrv = curproxy->srv;
7242 while (newsrv != NULL) {
7243 if (!newsrv->puid) {
7244 /* server ID not set, use automatic numbering with first
7245 * spare entry starting with next_svid.
7246 */
7247 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7248 newsrv->conf.id.key = newsrv->puid = next_id;
7249 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7250 }
7251 next_id++;
7252 newsrv = newsrv->next;
7253 }
7254
Willy Tarreau20697042007-11-15 23:26:18 +01007255 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007256 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007257
Willy Tarreau62c3be22012-01-20 13:12:32 +01007258 /*
7259 * If this server supports a maxconn parameter, it needs a dedicated
7260 * tasks to fill the emptied slots when a connection leaves.
7261 * Also, resolve deferred tracking dependency if needed.
7262 */
7263 newsrv = curproxy->srv;
7264 while (newsrv != NULL) {
7265 if (newsrv->minconn > newsrv->maxconn) {
7266 /* Only 'minconn' was specified, or it was higher than or equal
7267 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7268 * this will avoid further useless expensive computations.
7269 */
7270 newsrv->maxconn = newsrv->minconn;
7271 } else if (newsrv->maxconn && !newsrv->minconn) {
7272 /* minconn was not specified, so we set it to maxconn */
7273 newsrv->minconn = newsrv->maxconn;
7274 }
7275
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007276#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007277 if (newsrv->use_ssl || newsrv->check.use_ssl)
7278 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007279#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007280
Willy Tarreau2f075e92013-12-03 11:11:34 +01007281 /* set the check type on the server */
7282 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7283
Willy Tarreau62c3be22012-01-20 13:12:32 +01007284 if (newsrv->trackit) {
7285 struct proxy *px;
7286 struct server *srv;
7287 char *pname, *sname;
7288
7289 pname = newsrv->trackit;
7290 sname = strrchr(pname, '/');
7291
7292 if (sname)
7293 *sname++ = '\0';
7294 else {
7295 sname = pname;
7296 pname = NULL;
7297 }
7298
7299 if (pname) {
7300 px = findproxy(pname, PR_CAP_BE);
7301 if (!px) {
7302 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7303 proxy_type_str(curproxy), curproxy->id,
7304 newsrv->id, pname);
7305 cfgerr++;
7306 goto next_srv;
7307 }
7308 } else
7309 px = curproxy;
7310
7311 srv = findserver(px, sname);
7312 if (!srv) {
7313 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7314 proxy_type_str(curproxy), curproxy->id,
7315 newsrv->id, sname);
7316 cfgerr++;
7317 goto next_srv;
7318 }
7319
Willy Tarreauff5ae352013-12-11 20:36:34 +01007320 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007321 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7322 "tracking as it does not have checks enabled.\n",
7323 proxy_type_str(curproxy), curproxy->id,
7324 newsrv->id, px->id, srv->id);
7325 cfgerr++;
7326 goto next_srv;
7327 }
7328
7329 if (curproxy != px &&
7330 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7331 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7332 "tracking: disable-on-404 option inconsistency.\n",
7333 proxy_type_str(curproxy), curproxy->id,
7334 newsrv->id, px->id, srv->id);
7335 cfgerr++;
7336 goto next_srv;
7337 }
7338
7339 /* if the other server is forced disabled, we have to do the same here */
7340 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007341 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007342 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007343 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007344 }
7345
7346 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007347 newsrv->tracknext = srv->trackers;
7348 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007349
7350 free(newsrv->trackit);
7351 newsrv->trackit = NULL;
7352 }
7353 next_srv:
7354 newsrv = newsrv->next;
7355 }
7356
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007357 /* We have to initialize the server lookup mechanism depending
7358 * on what LB algorithm was choosen.
7359 */
7360
7361 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7362 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7363 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007364 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7365 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7366 init_server_map(curproxy);
7367 } else {
7368 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7369 fwrr_init_server_groups(curproxy);
7370 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007371 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007372
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007373 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007374 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7375 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7376 fwlc_init_server_tree(curproxy);
7377 } else {
7378 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7379 fas_init_server_tree(curproxy);
7380 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007381 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007382
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007383 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007384 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7385 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7386 chash_init_server_tree(curproxy);
7387 } else {
7388 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7389 init_server_map(curproxy);
7390 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007391 break;
7392 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007393
7394 if (curproxy->options & PR_O_LOGASAP)
7395 curproxy->to_log &= ~LW_BYTES;
7396
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007397 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007398 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007399 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7400 proxy_type_str(curproxy), curproxy->id);
7401 err_code |= ERR_WARN;
7402 }
7403
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007404 if (curproxy->mode != PR_MODE_HTTP) {
7405 int optnum;
7406
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007407 if (curproxy->uri_auth) {
7408 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7409 proxy_type_str(curproxy), curproxy->id);
7410 err_code |= ERR_WARN;
7411 curproxy->uri_auth = NULL;
7412 }
7413
Willy Tarreau87cf5142011-08-19 22:57:24 +02007414 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007415 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7416 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7417 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007418 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007419 }
7420
7421 if (curproxy->options & PR_O_ORGTO) {
7422 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7423 "originalto", proxy_type_str(curproxy), curproxy->id);
7424 err_code |= ERR_WARN;
7425 curproxy->options &= ~PR_O_ORGTO;
7426 }
7427
7428 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7429 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7430 (curproxy->cap & cfg_opts[optnum].cap) &&
7431 (curproxy->options & cfg_opts[optnum].val)) {
7432 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7433 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7434 err_code |= ERR_WARN;
7435 curproxy->options &= ~cfg_opts[optnum].val;
7436 }
7437 }
7438
7439 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7440 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7441 (curproxy->cap & cfg_opts2[optnum].cap) &&
7442 (curproxy->options2 & cfg_opts2[optnum].val)) {
7443 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7444 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7445 err_code |= ERR_WARN;
7446 curproxy->options2 &= ~cfg_opts2[optnum].val;
7447 }
7448 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007449
Pieter Baauwd551fb52013-05-08 22:49:23 +02007450#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007451 if (curproxy->conn_src.bind_hdr_occ) {
7452 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007453 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007454 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007455 err_code |= ERR_WARN;
7456 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007457#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007458 }
7459
Willy Tarreaubaaee002006-06-26 02:48:02 +02007460 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007461 * ensure that we're not cross-dressing a TCP server into HTTP.
7462 */
7463 newsrv = curproxy->srv;
7464 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007465 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007466 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7467 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007468 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007469 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007470
Willy Tarreau0cec3312011-10-31 13:49:26 +01007471 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7472 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7473 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7474 err_code |= ERR_WARN;
7475 }
7476
Willy Tarreau82ffa392013-08-13 17:19:08 +02007477 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7478 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7479 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7480 err_code |= ERR_WARN;
7481 }
7482
Pieter Baauwd551fb52013-05-08 22:49:23 +02007483#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007484 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7485 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007486 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 +01007487 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007488 err_code |= ERR_WARN;
7489 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007490#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007491 newsrv = newsrv->next;
7492 }
7493
Willy Tarreauc1a21672009-08-16 22:37:44 +02007494 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007495 if (!curproxy->accept)
7496 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007497
Willy Tarreauc1a21672009-08-16 22:37:44 +02007498 if (curproxy->tcp_req.inspect_delay ||
7499 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007500 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007501
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007502 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007503 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007504 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007505 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007506
7507 /* both TCP and HTTP must check switching rules */
7508 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7509 }
7510
7511 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007512 if (curproxy->tcp_req.inspect_delay ||
7513 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7514 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7515
Emeric Brun97679e72010-09-23 17:56:44 +02007516 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7517 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7518
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007519 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007520 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007521 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007522 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007523
7524 /* If the backend does requires RDP cookie persistence, we have to
7525 * enable the corresponding analyser.
7526 */
7527 if (curproxy->options2 & PR_O2_RDPC_PRST)
7528 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7529 }
7530
Emeric Brunc52962f2012-11-15 18:28:02 +01007531#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007532 /* Configure SSL for each bind line.
7533 * Note: if configuration fails at some point, the ->ctx member
7534 * remains NULL so that listeners can later detach.
7535 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007536 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007537 if (!bind_conf->is_ssl) {
7538 if (bind_conf->default_ctx) {
7539 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7540 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7541 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007542 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007543 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007544 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007545 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007546 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007547 cfgerr++;
7548 continue;
7549 }
7550
Emeric Brun4b3091e2012-09-24 15:48:52 +02007551 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007552 Alert("Unable to allocate SSL session cache.\n");
7553 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007554 continue;
7555 }
7556
Emeric Brunfc0421f2012-09-07 17:30:07 +02007557 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007558 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007559 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007560#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007561
Willy Tarreaue6b98942007-10-29 01:09:36 +01007562 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007563 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007564 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007565 if (!listener->luid) {
7566 /* listener ID not set, use automatic numbering with first
7567 * spare entry starting with next_luid.
7568 */
7569 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7570 listener->conf.id.key = listener->luid = next_id;
7571 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007572 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007573 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007574
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007575 /* enable separate counters */
7576 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7577 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007578 if (!listener->name)
7579 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007580 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007581
Willy Tarreaue6b98942007-10-29 01:09:36 +01007582 if (curproxy->options & PR_O_TCP_NOLING)
7583 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007584 if (!listener->maxconn)
7585 listener->maxconn = curproxy->maxconn;
7586 if (!listener->backlog)
7587 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007588 if (!listener->maxaccept)
7589 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7590
7591 /* we want to have an optimal behaviour on single process mode to
7592 * maximize the work at once, but in multi-process we want to keep
7593 * some fairness between processes, so we target half of the max
7594 * number of events to be balanced over all the processes the proxy
7595 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7596 * used to disable the limit.
7597 */
7598 if (listener->maxaccept > 0) {
7599 if (nbproc > 1)
7600 listener->maxaccept = (listener->maxaccept + 1) / 2;
7601 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7602 }
7603
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007604 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007605 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007606 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007607 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007608
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007609 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7610 listener->options |= LI_O_TCP_RULES;
7611
Willy Tarreaude3041d2010-05-31 10:56:17 +02007612 if (curproxy->mon_mask.s_addr)
7613 listener->options |= LI_O_CHK_MONNET;
7614
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007615 /* smart accept mode is automatic in HTTP mode */
7616 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007617 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007618 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7619 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007620 }
7621
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007622 /* Release unused SSL configs */
7623 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7624 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007625 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007626#ifdef USE_OPENSSL
7627 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007628 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007629 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007630 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007631 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007632#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007633 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007634
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007635 /* Check multi-process mode compatibility for the current proxy */
7636 if (global.nbproc > 1) {
7637 int nbproc = 0;
7638 if (curproxy->bind_proc) {
7639 int proc;
7640 for (proc = 0; proc < global.nbproc; proc++) {
7641 if (curproxy->bind_proc & (1 << proc)) {
7642 nbproc++;
7643 }
7644 }
7645 } else {
7646 nbproc = global.nbproc;
7647 }
7648 if (curproxy->table.peers.name) {
7649 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7650 curproxy->id);
7651 cfgerr++;
7652 }
7653 if (nbproc > 1) {
7654 if (curproxy->uri_auth) {
7655 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7656 curproxy->id);
7657 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7658 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7659 curproxy->id);
7660 }
7661 }
7662 if (curproxy->appsession_name) {
7663 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7664 curproxy->id);
7665 }
7666 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7667 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7668 curproxy->id);
7669 }
7670 }
7671 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007672
7673 /* create the task associated with the proxy */
7674 curproxy->task = task_new();
7675 if (curproxy->task) {
7676 curproxy->task->context = curproxy;
7677 curproxy->task->process = manage_proxy;
7678 /* no need to queue, it will be done automatically if some
7679 * listener gets limited.
7680 */
7681 curproxy->task->expire = TICK_ETERNITY;
7682 } else {
7683 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7684 curproxy->id);
7685 cfgerr++;
7686 }
7687
Willy Tarreaubaaee002006-06-26 02:48:02 +02007688 curproxy = curproxy->next;
7689 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007690
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007691 /* Check multi-process mode compatibility */
7692 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007693 if (global.stats_fe && !global.stats_fe->bind_proc) {
7694 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 +01007695 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007696 }
7697
7698 /* automatically compute fullconn if not set. We must not do it in the
7699 * loop above because cross-references are not yet fully resolved.
7700 */
7701 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7702 /* If <fullconn> is not set, let's set it to 10% of the sum of
7703 * the possible incoming frontend's maxconns.
7704 */
7705 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7706 struct proxy *fe;
7707 int total = 0;
7708
7709 /* sum up the number of maxconns of frontends which
7710 * reference this backend at least once or which are
7711 * the same one ('listen').
7712 */
7713 for (fe = proxy; fe; fe = fe->next) {
7714 struct switching_rule *rule;
7715 struct hdr_exp *exp;
7716 int found = 0;
7717
7718 if (!(fe->cap & PR_CAP_FE))
7719 continue;
7720
7721 if (fe == curproxy) /* we're on a "listen" instance */
7722 found = 1;
7723
7724 if (fe->defbe.be == curproxy) /* "default_backend" */
7725 found = 1;
7726
7727 /* check if a "use_backend" rule matches */
7728 if (!found) {
7729 list_for_each_entry(rule, &fe->switching_rules, list) {
7730 if (rule->be.backend == curproxy) {
7731 found = 1;
7732 break;
7733 }
7734 }
7735 }
7736
7737 /* check if a "reqsetbe" rule matches */
7738 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7739 if (exp->action == ACT_SETBE &&
7740 (struct proxy *)exp->replace == curproxy) {
7741 found = 1;
7742 break;
7743 }
7744 }
7745
7746 /* now we've checked all possible ways to reference a backend
7747 * from a frontend.
7748 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007749 if (!found)
7750 continue;
7751 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007752 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007753 /* we have the sum of the maxconns in <total>. We only
7754 * keep 10% of that sum to set the default fullconn, with
7755 * a hard minimum of 1 (to avoid a divide by zero).
7756 */
7757 curproxy->fullconn = (total + 9) / 10;
7758 if (!curproxy->fullconn)
7759 curproxy->fullconn = 1;
7760 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007761 }
7762
Willy Tarreau056f5682010-06-06 15:51:11 +02007763 /* initialize stick-tables on backend capable proxies. This must not
7764 * be done earlier because the data size may be discovered while parsing
7765 * other proxies.
7766 */
Godbach9703e662013-12-11 21:11:41 +08007767 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007768 if (curproxy->state == PR_STSTOPPED)
7769 continue;
7770
Godbach9703e662013-12-11 21:11:41 +08007771 if (!stktable_init(&curproxy->table)) {
7772 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7773 cfgerr++;
7774 }
7775 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007776
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007777 /*
7778 * Recount currently required checks.
7779 */
7780
7781 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7782 int optnum;
7783
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007784 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7785 if (curproxy->options & cfg_opts[optnum].val)
7786 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007787
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007788 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7789 if (curproxy->options2 & cfg_opts2[optnum].val)
7790 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007791 }
7792
Willy Tarreau122541c2011-09-07 21:24:49 +02007793 if (peers) {
7794 struct peers *curpeers = peers, **last;
7795 struct peer *p, *pb;
7796
7797 /* Remove all peers sections which don't have a valid listener.
7798 * This can happen when a peers section is never referenced and
7799 * does not contain a local peer.
7800 */
7801 last = &peers;
7802 while (*last) {
7803 curpeers = *last;
7804 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007805 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007806 last = &curpeers->next;
7807 continue;
7808 }
7809
7810 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7811 curpeers->id, localpeer);
7812
7813 p = curpeers->remote;
7814 while (p) {
7815 pb = p->next;
7816 free(p->id);
7817 free(p);
7818 p = pb;
7819 }
7820
7821 /* Destroy and unlink this curpeers section.
7822 * Note: curpeers is backed up into *last.
7823 */
7824 free(curpeers->id);
7825 curpeers = curpeers->next;
7826 free(*last);
7827 *last = curpeers;
7828 }
7829 }
7830
Willy Tarreau34eb6712011-10-24 18:15:04 +02007831 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007832 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007833 MEM_F_SHARED);
7834
Willy Tarreaubb925012009-07-23 13:36:36 +02007835 if (cfgerr > 0)
7836 err_code |= ERR_ALERT | ERR_FATAL;
7837 out:
7838 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007839}
7840
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007841/*
7842 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7843 * parsing sessions.
7844 */
7845void cfg_register_keywords(struct cfg_kw_list *kwl)
7846{
7847 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7848}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007849
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007850/*
7851 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7852 */
7853void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7854{
7855 LIST_DEL(&kwl->list);
7856 LIST_INIT(&kwl->list);
7857}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007858
7859/*
7860 * Local variables:
7861 * c-indent-level: 8
7862 * c-basic-offset: 8
7863 * End:
7864 */