blob: f13b9679d102c6beeac350424d2de190ee9b5ffb [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100133 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100206 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100207 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
209 str = next;
210 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100211 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 *next++ = 0;
213 }
214
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100215 ss2 = str2sa_range(str, &port, &end, err,
216 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
217 if (!ss2)
218 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100220 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100221 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100226 if (!port || !end) {
227 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
228 goto fail;
229 }
230
Emeric Bruned760922010-10-22 17:59:25 +0200231 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200232 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200233 goto fail;
234 }
235
236 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200237 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200238 goto fail;
239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100241 else if (ss2->ss_family == AF_UNSPEC) {
242 socklen_t addr_len;
243
244 /* We want to attach to an already bound fd whose number
245 * is in the addr part of ss2 when cast to sockaddr_in.
246 * Note that by definition there is a single listener.
247 * We still have to determine the address family to
248 * register the correct protocol.
249 */
250 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
251 addr_len = sizeof(*ss2);
252 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
253 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
254 goto fail;
255 }
256
257 port = end = get_host_port(ss2);
258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100260 /* OK the address looks correct */
261 ss = *ss2;
262
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 for (; port <= end; port++) {
264 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100265 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau40aa0702013-03-10 23:51:38 +0100271 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200273 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100414/* Report it if a request ACL condition uses some keywords that are incompatible
415 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
416 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
417 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100419static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100420{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100421 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200422 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100425 return 0;
426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 acl = acl_cond_conflicts(cond, where);
428 if (acl) {
429 if (acl->name && *acl->name)
430 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
431 file, line, acl->name, sample_ckp_names(where));
432 else
433 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200434 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100435 return ERR_WARN;
436 }
437 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100438 return 0;
439
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100440 if (acl->name && *acl->name)
441 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200442 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 else
444 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100446 return ERR_WARN;
447}
448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200468 else if (!strcmp(args[0], "ca-base")) {
469#ifdef USE_OPENSSL
470 if (global.ca_base != NULL) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT;
473 goto out;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
479 }
480 global.ca_base = strdup(args[1]);
481#else
482 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
485#endif
486 }
487 else if (!strcmp(args[0], "crt-base")) {
488#ifdef USE_OPENSSL
489 if (global.crt_base != NULL) {
490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
491 err_code |= ERR_ALERT;
492 goto out;
493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
498 }
499 global.crt_base = strdup(args[1]);
500#else
501 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504#endif
505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200506 else if (!strcmp(args[0], "daemon")) {
507 global.mode |= MODE_DAEMON;
508 }
509 else if (!strcmp(args[0], "debug")) {
510 global.mode |= MODE_DEBUG;
511 }
512 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100513 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200515 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100521 else if (!strcmp(args[0], "nosplice")) {
522 global.tune.options &= ~GTUNE_USE_SPLICE;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 else if (!strcmp(args[0], "quiet")) {
525 global.mode |= MODE_QUIET;
526 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200527 else if (!strcmp(args[0], "tune.maxpollevents")) {
528 if (global.tune.maxpollevents != 0) {
529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 err_code |= ERR_ALERT;
531 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 }
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 global.tune.maxpollevents = atol(args[1]);
539 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100540 else if (!strcmp(args[0], "tune.maxaccept")) {
541 if (global.tune.maxaccept != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 err_code |= ERR_ALERT;
544 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 global.tune.maxaccept = atol(args[1]);
552 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200553 else if (!strcmp(args[0], "tune.chksize")) {
554 if (*(args[1]) == 0) {
555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT | ERR_FATAL;
557 goto out;
558 }
559 global.tune.chksize = atol(args[1]);
560 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200561#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100562 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.sslcachesize = atol(args[1]);
569 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100570 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
571 unsigned int ssllifetime;
572 const char *res;
573
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579
580 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
581 if (res) {
582 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
583 file, linenum, *res, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587
588 global.tune.ssllifetime = ssllifetime;
589 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100590 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.tune.ssl_max_record = atol(args[1]);
597 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200599 else if (!strcmp(args[0], "tune.bufsize")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.bufsize = atol(args[1]);
606 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
607 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100608 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100609 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200610 }
611 else if (!strcmp(args[0], "tune.maxrewrite")) {
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617 global.tune.maxrewrite = atol(args[1]);
618 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
619 global.tune.maxrewrite = global.tune.bufsize / 2;
620 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100621 else if (!strcmp(args[0], "tune.idletimer")) {
622 unsigned int idle;
623 const char *res;
624
625 if (*(args[1]) == 0) {
626 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT | ERR_FATAL;
628 goto out;
629 }
630
631 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
632 if (res) {
633 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
634 file, linenum, *res, args[0]);
635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
637 }
638
639 if (idle > 65535) {
640 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.idle_timer = idle;
645 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100646 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
647 if (global.tune.client_rcvbuf != 0) {
648 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT;
650 goto out;
651 }
652 if (*(args[1]) == 0) {
653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656 }
657 global.tune.client_rcvbuf = atol(args[1]);
658 }
659 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
660 if (global.tune.server_rcvbuf != 0) {
661 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT;
663 goto out;
664 }
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
669 }
670 global.tune.server_rcvbuf = atol(args[1]);
671 }
672 else if (!strcmp(args[0], "tune.sndbuf.client")) {
673 if (global.tune.client_sndbuf != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT;
676 goto out;
677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.client_sndbuf = atol(args[1]);
684 }
685 else if (!strcmp(args[0], "tune.sndbuf.server")) {
686 if (global.tune.server_sndbuf != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT;
689 goto out;
690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 global.tune.server_sndbuf = atol(args[1]);
697 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200698 else if (!strcmp(args[0], "tune.pipesize")) {
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.pipesize = atol(args[1]);
705 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100706 else if (!strcmp(args[0], "tune.http.cookielen")) {
707 if (*(args[1]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712 global.tune.cookie_len = atol(args[1]) + 1;
713 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200714 else if (!strcmp(args[0], "tune.http.maxhdr")) {
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.max_http_hdr = atol(args[1]);
721 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100722 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
723#ifdef USE_ZLIB
724 if (*args[1]) {
725 global.tune.zlibmemlevel = atoi(args[1]);
726 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
727 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
728 file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 } else {
733 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
734 file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#else
739 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742#endif
743 }
744 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
745#ifdef USE_ZLIB
746 if (*args[1]) {
747 global.tune.zlibwindowsize = atoi(args[1]);
748 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
749 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
750 file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 } else {
755 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760#else
761 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764#endif
765 }
William Lallemandf3747832012-11-09 12:33:10 +0100766 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
767 if (*args[1]) {
768 global.tune.comp_maxlevel = atoi(args[1]);
769 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
770 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
771 file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 } else {
776 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
777 file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 else if (!strcmp(args[0], "uid")) {
783 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200784 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT;
786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 }
788 if (*(args[1]) == 0) {
789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 }
793 global.uid = atol(args[1]);
794 }
795 else if (!strcmp(args[0], "gid")) {
796 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200797 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200798 err_code |= ERR_ALERT;
799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 }
801 if (*(args[1]) == 0) {
802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 }
806 global.gid = atol(args[1]);
807 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200808 /* user/group name handling */
809 else if (!strcmp(args[0], "user")) {
810 struct passwd *ha_user;
811 if (global.uid != 0) {
812 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
814 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200815 }
816 errno = 0;
817 ha_user = getpwnam(args[1]);
818 if (ha_user != NULL) {
819 global.uid = (int)ha_user->pw_uid;
820 }
821 else {
822 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200823 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200824 }
825 }
826 else if (!strcmp(args[0], "group")) {
827 struct group *ha_group;
828 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200829 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
831 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200832 }
833 errno = 0;
834 ha_group = getgrnam(args[1]);
835 if (ha_group != NULL) {
836 global.gid = (int)ha_group->gr_gid;
837 }
838 else {
839 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200840 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200841 }
842 }
843 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.nbproc = atol(args[1]);
851 }
852 else if (!strcmp(args[0], "maxconn")) {
853 if (global.maxconn != 0) {
854 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200855 err_code |= ERR_ALERT;
856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 }
863 global.maxconn = atol(args[1]);
864#ifdef SYSTEM_MAXCONN
865 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
866 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
867 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 }
870#endif /* SYSTEM_MAXCONN */
871 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200872 else if (!strcmp(args[0], "maxsslconn")) {
873#ifdef USE_OPENSSL
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.maxsslconn = atol(args[1]);
880#else
Emeric Brun0914df82012-10-02 18:45:42 +0200881 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200884#endif
885 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100886 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
887#ifdef USE_OPENSSL
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 free(global.listen_default_ciphers);
894 global.listen_default_ciphers = strdup(args[1]);
895#else
896 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899#endif
900 }
901 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
902#ifdef USE_OPENSSL
903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908 free(global.connect_default_ciphers);
909 global.connect_default_ciphers = strdup(args[1]);
910#else
911 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914#endif
915 }
Emeric Brun850efd52014-01-29 12:24:34 +0100916 else if (!strcmp(args[0], "ssl-server-verify")) {
917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 if (strcmp(args[1],"none") == 0)
923 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
924 else if (strcmp(args[1],"required") == 0)
925 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
926 else {
927 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200932 else if (!strcmp(args[0], "maxconnrate")) {
933 if (global.cps_lim != 0) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT;
936 goto out;
937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.cps_lim = atol(args[1]);
944 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200945 else if (!strcmp(args[0], "maxsessrate")) {
946 if (global.sps_lim != 0) {
947 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT;
949 goto out;
950 }
951 if (*(args[1]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
956 global.sps_lim = atol(args[1]);
957 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200958 else if (!strcmp(args[0], "maxsslrate")) {
959 if (global.ssl_lim != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
961 err_code |= ERR_ALERT;
962 goto out;
963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.ssl_lim = atol(args[1]);
970 }
William Lallemandd85f9172012-11-09 17:05:39 +0100971 else if (!strcmp(args[0], "maxcomprate")) {
972 if (*(args[1]) == 0) {
973 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 global.comp_rate_lim = atoi(args[1]) * 1024;
978 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100979 else if (!strcmp(args[0], "maxpipes")) {
980 if (global.maxpipes != 0) {
981 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200982 err_code |= ERR_ALERT;
983 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100984 }
985 if (*(args[1]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100989 }
990 global.maxpipes = atol(args[1]);
991 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100992 else if (!strcmp(args[0], "maxzlibmem")) {
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
William Lallemande3a7d992012-11-20 11:25:20 +0100998 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100999 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001000 else if (!strcmp(args[0], "maxcompcpuusage")) {
1001 if (*(args[1]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001007 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001008 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012}
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 else if (!strcmp(args[0], "ulimit-n")) {
1015 if (global.rlimit_nofile != 0) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT;
1018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 }
1020 if (*(args[1]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
1025 global.rlimit_nofile = atol(args[1]);
1026 }
1027 else if (!strcmp(args[0], "chroot")) {
1028 if (global.chroot != NULL) {
1029 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001030 err_code |= ERR_ALERT;
1031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 }
1033 if (*(args[1]) == 0) {
1034 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 global.chroot = strdup(args[1]);
1039 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001040 else if (!strcmp(args[0], "description")) {
1041 int i, len=0;
1042 char *d;
1043
1044 if (!*args[1]) {
1045 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1046 file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 for(i=1; *args[i]; i++)
1052 len += strlen(args[i])+1;
1053
1054 if (global.desc)
1055 free(global.desc);
1056
1057 global.desc = d = (char *)calloc(1, len);
1058
1059 d += sprintf(d, "%s", args[1]);
1060 for(i=2; *args[i]; i++)
1061 d += sprintf(d, " %s", args[i]);
1062 }
1063 else if (!strcmp(args[0], "node")) {
1064 int i;
1065 char c;
1066
1067 for (i=0; args[1][i]; i++) {
1068 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001069 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1070 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001071 break;
1072 }
1073
1074 if (!i || args[1][i]) {
1075 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1076 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1077 file, linenum, args[0]);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081
1082 if (global.node)
1083 free(global.node);
1084
1085 global.node = strdup(args[1]);
1086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 else if (!strcmp(args[0], "pidfile")) {
1088 if (global.pidfile != NULL) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
1098 global.pidfile = strdup(args[1]);
1099 }
Emeric Bruned760922010-10-22 17:59:25 +02001100 else if (!strcmp(args[0], "unix-bind")) {
1101 int cur_arg = 1;
1102 while (*(args[cur_arg])) {
1103 if (!strcmp(args[cur_arg], "prefix")) {
1104 if (global.unix_bind.prefix != NULL) {
1105 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1106 err_code |= ERR_ALERT;
1107 cur_arg += 2;
1108 continue;
1109 }
1110
1111 if (*(args[cur_arg+1]) == 0) {
1112 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1117 cur_arg += 2;
1118 continue;
1119 }
1120
1121 if (!strcmp(args[cur_arg], "mode")) {
1122
1123 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1124 cur_arg += 2;
1125 continue;
1126 }
1127
1128 if (!strcmp(args[cur_arg], "uid")) {
1129
1130 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1131 cur_arg += 2;
1132 continue;
1133 }
1134
1135 if (!strcmp(args[cur_arg], "gid")) {
1136
1137 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1138 cur_arg += 2;
1139 continue;
1140 }
1141
1142 if (!strcmp(args[cur_arg], "user")) {
1143 struct passwd *user;
1144
1145 user = getpwnam(args[cur_arg + 1]);
1146 if (!user) {
1147 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1148 file, linenum, args[0], args[cur_arg + 1 ]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152
1153 global.unix_bind.ux.uid = user->pw_uid;
1154 cur_arg += 2;
1155 continue;
1156 }
1157
1158 if (!strcmp(args[cur_arg], "group")) {
1159 struct group *group;
1160
1161 group = getgrnam(args[cur_arg + 1]);
1162 if (!group) {
1163 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1164 file, linenum, args[0], args[cur_arg + 1 ]);
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168
1169 global.unix_bind.ux.gid = group->gr_gid;
1170 cur_arg += 2;
1171 continue;
1172 }
1173
Willy Tarreaub48f9582011-09-05 01:17:06 +02001174 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001175 file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
1179 }
William Lallemand0f99e342011-10-12 17:50:54 +02001180 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1181 /* delete previous herited or defined syslog servers */
1182 struct logsrv *back;
1183 struct logsrv *tmp;
1184
1185 if (*(args[1]) != 0) {
1186 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190
1191 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1192 LIST_DEL(&tmp->list);
1193 free(tmp);
1194 }
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001197 struct sockaddr_storage *sk;
1198 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001199 struct logsrv *logsrv;
1200
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 if (*(args[1]) == 0 || *(args[2]) == 0) {
1202 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
William Lallemand0f99e342011-10-12 17:50:54 +02001206
1207 logsrv = calloc(1, sizeof(struct logsrv));
1208
1209 logsrv->facility = get_log_facility(args[2]);
1210 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001213 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
1215
William Lallemand0f99e342011-10-12 17:50:54 +02001216 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001218 logsrv->level = get_log_level(args[3]);
1219 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001221 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001222 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 }
1224 }
1225
William Lallemand0f99e342011-10-12 17:50:54 +02001226 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001227 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001228 logsrv->minlvl = get_log_level(args[4]);
1229 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001230 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001232 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001233 }
1234 }
1235
Willy Tarreau902636f2013-03-10 19:44:48 +01001236 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001237 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001238 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001239 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001240 free(logsrv);
1241 goto out;
1242 }
1243 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001244
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001245 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001246 if (port1 != port2) {
1247 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1248 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001249 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001250 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001251 goto out;
1252 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001253
William Lallemand0f99e342011-10-12 17:50:54 +02001254 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001255 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001256 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258
William Lallemand0f99e342011-10-12 17:50:54 +02001259 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001260 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001261 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1262 char *name;
1263 int len;
1264
1265 if (global.log_send_hostname != NULL) {
1266 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT;
1268 goto out;
1269 }
1270
1271 if (*(args[1]))
1272 name = args[1];
1273 else
1274 name = hostname;
1275
1276 len = strlen(name);
1277
1278 /* We'll add a space after the name to respect the log format */
1279 free(global.log_send_hostname);
1280 global.log_send_hostname = malloc(len + 2);
1281 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1282 }
Kevinm48936af2010-12-22 16:08:21 +00001283 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1284 if (*(args[1]) == 0) {
1285 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 free(global.log_tag);
1290 global.log_tag = strdup(args[1]);
1291 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001292 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1293 if (global.spread_checks != 0) {
1294 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001295 err_code |= ERR_ALERT;
1296 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001297 }
1298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001302 }
1303 global.spread_checks = atol(args[1]);
1304 if (global.spread_checks < 0 || global.spread_checks > 50) {
1305 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001306 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001309 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1310#ifdef USE_CPU_AFFINITY
1311 int cur_arg, i;
1312 unsigned int proc = 0;
1313 unsigned long cpus = 0;
1314
1315 if (strcmp(args[1], "all") == 0)
1316 proc = 0xFFFFFFFF;
1317 else if (strcmp(args[1], "odd") == 0)
1318 proc = 0x55555555;
1319 else if (strcmp(args[1], "even") == 0)
1320 proc = 0xAAAAAAAA;
1321 else {
1322 proc = atoi(args[1]);
1323 if (proc >= 1 && proc <= 32)
1324 proc = 1 << (proc - 1);
1325 }
1326
1327 if (!proc || !*args[2]) {
1328 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
1334 cur_arg = 2;
1335 while (*args[cur_arg]) {
1336 unsigned int low, high;
1337
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001338 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001339 char *dash = strchr(args[cur_arg], '-');
1340
1341 low = high = str2uic(args[cur_arg]);
1342 if (dash)
1343 high = str2uic(dash + 1);
1344
1345 if (high < low) {
1346 unsigned int swap = low;
1347 low = high;
1348 high = swap;
1349 }
1350
1351 if (low < 0 || high >= sizeof(long) * 8) {
1352 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1353 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357
1358 while (low <= high)
1359 cpus |= 1UL << low++;
1360 }
1361 else {
1362 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1363 file, linenum, args[0], args[cur_arg]);
1364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
1366 }
1367 cur_arg++;
1368 }
1369 for (i = 0; i < 32; i++)
1370 if (proc & (1 << i))
1371 global.cpu_map[i] = cpus;
1372#else
1373 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376#endif
1377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001379 struct cfg_kw_list *kwl;
1380 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001381 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001382
1383 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1384 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1385 if (kwl->kw[index].section != CFG_GLOBAL)
1386 continue;
1387 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001388 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001389 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001390 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001392 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001393 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001394 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001395 err_code |= ERR_WARN;
1396 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001397 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001399 }
1400 }
1401 }
1402
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001404 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406
Willy Tarreau058e9072009-07-20 09:30:05 +02001407 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001408 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410}
1411
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001412void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001414 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 defproxy.mode = PR_MODE_TCP;
1416 defproxy.state = PR_STNEW;
1417 defproxy.maxconn = cfg_maxpconn;
1418 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419
Simon Horman66183002013-02-23 10:16:43 +09001420 defproxy.defsrv.check.inter = DEF_CHKINTR;
1421 defproxy.defsrv.check.fastinter = 0;
1422 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001423 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1424 defproxy.defsrv.agent.fastinter = 0;
1425 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001426 defproxy.defsrv.check.rise = DEF_RISETIME;
1427 defproxy.defsrv.check.fall = DEF_FALLTIME;
1428 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1429 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001430 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001431 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001432 defproxy.defsrv.maxqueue = 0;
1433 defproxy.defsrv.minconn = 0;
1434 defproxy.defsrv.maxconn = 0;
1435 defproxy.defsrv.slowstart = 0;
1436 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1437 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1438 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439}
1440
Willy Tarreauade5ec42010-01-28 19:33:49 +01001441
1442static int create_cond_regex_rule(const char *file, int line,
1443 struct proxy *px, int dir, int action, int flags,
1444 const char *cmd, const char *reg, const char *repl,
1445 const char **cond_start)
1446{
1447 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001448 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001449 const char *err;
1450 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001451 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001452
1453 if (px == &defproxy) {
1454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1455 err_code |= ERR_ALERT | ERR_FATAL;
1456 goto err;
1457 }
1458
1459 if (*reg == 0) {
1460 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto err;
1463 }
1464
1465 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1466 err_code |= ERR_WARN;
1467
Willy Tarreau5321c422010-01-28 20:35:13 +01001468 if (cond_start &&
1469 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001470 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1471 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1472 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto err;
1475 }
1476 }
1477 else if (cond_start && **cond_start) {
1478 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1479 file, line, cmd, *cond_start);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto err;
1482 }
1483
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001484 err_code |= warnif_cond_conflicts(cond,
1485 (dir == SMP_OPT_DIR_REQ) ?
1486 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1487 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1488 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001489
Willy Tarreauade5ec42010-01-28 19:33:49 +01001490 preg = calloc(1, sizeof(regex_t));
1491 if (!preg) {
1492 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1493 err_code = ERR_ALERT | ERR_FATAL;
1494 goto err;
1495 }
1496
1497 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1498 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1499 err_code = ERR_ALERT | ERR_FATAL;
1500 goto err;
1501 }
1502
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001503 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001504 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001505 if (repl && err) {
1506 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1507 file, line, cmd, *err);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto err;
1510 }
1511
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001512 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001513 err_code |= ERR_WARN;
1514
Willy Tarreauf4068b62012-05-08 17:37:49 +02001515 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001516 return err_code;
1517 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001518 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001519 free(preg);
1520 return err_code;
1521}
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001525 * Returns the error code, 0 if OK, or any combination of :
1526 * - ERR_ABORT: must abort ASAP
1527 * - ERR_FATAL: we can continue parsing but not start the service
1528 * - ERR_WARN: a warning has been emitted
1529 * - ERR_ALERT: an alert has been emitted
1530 * Only the two first ones can stop processing, the two others are just
1531 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001533int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1534{
1535 static struct peers *curpeers = NULL;
1536 struct peer *newpeer = NULL;
1537 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001538 struct bind_conf *bind_conf;
1539 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001540 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001541 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001542
1543 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001544 if (!*args[1]) {
1545 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001546 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001547 goto out;
1548 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 err = invalid_char(args[1]);
1551 if (err) {
1552 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1553 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001554 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001555 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001556 }
1557
1558 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1559 /*
1560 * If there are two proxies with the same name only following
1561 * combinations are allowed:
1562 */
1563 if (strcmp(curpeers->id, args[1]) == 0) {
1564 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1565 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1566 err_code |= ERR_WARN;
1567 }
1568 }
1569
1570 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1571 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1572 err_code |= ERR_ALERT | ERR_ABORT;
1573 goto out;
1574 }
1575
1576 curpeers->next = peers;
1577 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001578 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001579 curpeers->conf.line = linenum;
1580 curpeers->last_change = now.tv_sec;
1581 curpeers->id = strdup(args[1]);
1582 }
1583 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001584 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001585 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001586 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001587
1588 if (!*args[2]) {
1589 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1590 file, linenum, args[0]);
1591 err_code |= ERR_ALERT | ERR_FATAL;
1592 goto out;
1593 }
1594
1595 err = invalid_char(args[1]);
1596 if (err) {
1597 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1598 file, linenum, *err, args[1]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
1601 }
1602
1603 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1604 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1605 err_code |= ERR_ALERT | ERR_ABORT;
1606 goto out;
1607 }
1608
1609 /* the peers are linked backwards first */
1610 curpeers->count++;
1611 newpeer->next = curpeers->remote;
1612 curpeers->remote = newpeer;
1613 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001614 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001615 newpeer->conf.line = linenum;
1616
1617 newpeer->last_change = now.tv_sec;
1618 newpeer->id = strdup(args[1]);
1619
Willy Tarreau902636f2013-03-10 19:44:48 +01001620 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001621 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001622 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001625 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001626
1627 proto = protocol_by_family(sk->ss_family);
1628 if (!proto || !proto->connect) {
1629 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1630 file, linenum, args[0], args[1]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001634
1635 if (port1 != port2) {
1636 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1637 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
1640 }
1641
Willy Tarreau2aa38802013-02-20 19:20:59 +01001642 if (!port1) {
1643 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1644 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
1647 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001648
Emeric Brun32da3c42010-09-23 18:39:19 +02001649 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001650 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001651 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001652 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001653
Emeric Brun32da3c42010-09-23 18:39:19 +02001654 if (strcmp(newpeer->id, localpeer) == 0) {
1655 /* Current is local peer, it define a frontend */
1656 newpeer->local = 1;
1657
1658 if (!curpeers->peers_fe) {
1659 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1660 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1661 err_code |= ERR_ALERT | ERR_ABORT;
1662 goto out;
1663 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001664
Willy Tarreau237250c2011-07-29 01:49:03 +02001665 init_new_proxy(curpeers->peers_fe);
1666 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001667
1668 curpeers->peers_fe->last_change = now.tv_sec;
1669 curpeers->peers_fe->id = strdup(args[1]);
1670 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001671 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001672 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1673 curpeers->peers_fe->timeout.connect = 5000;
1674 curpeers->peers_fe->accept = peer_accept;
1675 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001676 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1677 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001678
1679 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1680
Willy Tarreau902636f2013-03-10 19:44:48 +01001681 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1682 if (errmsg && *errmsg) {
1683 indent_msg(&errmsg, 2);
1684 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001685 }
1686 else
1687 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1688 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001689 err_code |= ERR_FATAL;
1690 goto out;
1691 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001692
1693 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1694 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1695 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1696 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1697 l->accept = session_accept;
1698 l->handler = process_session;
1699 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1700 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1701 global.maxsock += l->maxconn;
1702 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001703 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001704 else {
1705 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1706 file, linenum, args[0], args[1],
1707 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1708 err_code |= ERR_FATAL;
1709 goto out;
1710 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 }
1712 } /* neither "peer" nor "peers" */
1713 else if (*args[0] != 0) {
1714 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
1717 }
1718
1719out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001720 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 return err_code;
1722}
1723
Simon Horman69d29f92013-02-23 15:14:19 +09001724static int init_check(struct check *check, int type, const char * file, int linenum)
1725{
1726 check->type = type;
1727
1728 /* Allocate buffer for requests... */
1729 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1730 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1731 return ERR_ALERT | ERR_ABORT;
1732 }
1733 check->bi->size = global.tune.chksize;
1734
1735 /* Allocate buffer for responses... */
1736 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1737 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1738 return ERR_ALERT | ERR_ABORT;
1739 }
1740 check->bo->size = global.tune.chksize;
1741
1742 /* Allocate buffer for partial results... */
1743 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1744 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1745 return ERR_ALERT | ERR_ABORT;
1746 }
1747
1748 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1749
1750 return 0;
1751}
Emeric Brun32da3c42010-09-23 18:39:19 +02001752
Willy Tarreau3842f002009-06-14 11:39:52 +02001753int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754{
1755 static struct proxy *curproxy = NULL;
1756 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001757 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001758 int rc;
1759 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001760 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001761 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001762 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001763 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001764 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765
Willy Tarreau977b8e42006-12-29 14:19:17 +01001766 if (!strcmp(args[0], "listen"))
1767 rc = PR_CAP_LISTEN;
1768 else if (!strcmp(args[0], "frontend"))
1769 rc = PR_CAP_FE | PR_CAP_RS;
1770 else if (!strcmp(args[0], "backend"))
1771 rc = PR_CAP_BE | PR_CAP_RS;
1772 else if (!strcmp(args[0], "ruleset"))
1773 rc = PR_CAP_RS;
1774 else
1775 rc = PR_CAP_NONE;
1776
1777 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 if (!*args[1]) {
1779 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1780 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1781 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001782 err_code |= ERR_ALERT | ERR_ABORT;
1783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001785
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001786 err = invalid_char(args[1]);
1787 if (err) {
1788 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1789 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001790 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001791 }
1792
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001793 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1794 /*
1795 * If there are two proxies with the same name only following
1796 * combinations are allowed:
1797 *
1798 * listen backend frontend ruleset
1799 * listen - - - -
1800 * backend - - OK -
1801 * frontend - OK - -
1802 * ruleset - - - -
1803 */
1804
1805 if (!strcmp(curproxy->id, args[1]) &&
1806 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1807 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001808 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1809 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1810 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001811 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001812 }
1813 }
1814
Willy Tarreaubaaee002006-06-26 02:48:02 +02001815 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1816 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_ALERT | ERR_ABORT;
1818 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001819 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001820
Willy Tarreau97cb7802010-01-03 20:23:58 +01001821 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001822 curproxy->next = proxy;
1823 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001824 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1825 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001826 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001827 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001828 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829
1830 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001831 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001832 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001833
Willy Tarreau4348fad2012-09-20 16:48:07 +02001834 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1835
Willy Tarreau902636f2013-03-10 19:44:48 +01001836 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1837 if (errmsg && *errmsg) {
1838 indent_msg(&errmsg, 2);
1839 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001840 }
1841 else
1842 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1843 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001844 err_code |= ERR_FATAL;
1845 goto out;
1846 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001847
Willy Tarreau4348fad2012-09-20 16:48:07 +02001848 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001849 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001850 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001851 }
1852
1853 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001854 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001855 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001856
Willy Tarreaubaaee002006-06-26 02:48:02 +02001857 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001859 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001860 curproxy->no_options = defproxy.no_options;
1861 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001862 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001863 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001864 curproxy->except_net = defproxy.except_net;
1865 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001866 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001867 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001868
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001869 if (defproxy.fwdfor_hdr_len) {
1870 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1871 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1872 }
1873
Willy Tarreaub86db342009-11-30 11:50:16 +01001874 if (defproxy.orgto_hdr_len) {
1875 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1876 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1877 }
1878
Mark Lamourinec2247f02012-01-04 13:02:01 -05001879 if (defproxy.server_id_hdr_len) {
1880 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1881 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1882 }
1883
Willy Tarreau977b8e42006-12-29 14:19:17 +01001884 if (curproxy->cap & PR_CAP_FE) {
1885 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001886 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001887 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001888
1889 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001890 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1891 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001892
1893 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1894 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001895
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 if (curproxy->cap & PR_CAP_BE) {
1897 curproxy->fullconn = defproxy.fullconn;
1898 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001899
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001900 if (defproxy.check_req) {
1901 curproxy->check_req = calloc(1, defproxy.check_len);
1902 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1903 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001904 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001906 if (defproxy.expect_str) {
1907 curproxy->expect_str = strdup(defproxy.expect_str);
1908 if (defproxy.expect_regex) {
1909 /* note: this regex is known to be valid */
1910 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1911 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1912 }
1913 }
1914
Willy Tarreau67402132012-05-31 20:40:20 +02001915 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (defproxy.cookie_name)
1917 curproxy->cookie_name = strdup(defproxy.cookie_name);
1918 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001919 if (defproxy.cookie_domain)
1920 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001921
Willy Tarreau31936852010-10-06 16:59:56 +02001922 if (defproxy.cookie_maxidle)
1923 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1924
1925 if (defproxy.cookie_maxlife)
1926 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1927
Emeric Brun647caf12009-06-30 17:57:00 +02001928 if (defproxy.rdp_cookie_name)
1929 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1930 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1931
Willy Tarreau01732802007-11-01 22:48:15 +01001932 if (defproxy.url_param_name)
1933 curproxy->url_param_name = strdup(defproxy.url_param_name);
1934 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001935
Benoitaffb4812009-03-25 13:02:10 +01001936 if (defproxy.hh_name)
1937 curproxy->hh_name = strdup(defproxy.hh_name);
1938 curproxy->hh_len = defproxy.hh_len;
1939 curproxy->hh_match_domain = defproxy.hh_match_domain;
1940
Willy Tarreauef9a3602012-12-08 22:29:20 +01001941 if (defproxy.conn_src.iface_name)
1942 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1943 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001944 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001945#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001946 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001947#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001948 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001949
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001950 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001951 if (defproxy.capture_name)
1952 curproxy->capture_name = strdup(defproxy.capture_name);
1953 curproxy->capture_namelen = defproxy.capture_namelen;
1954 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956
Willy Tarreau977b8e42006-12-29 14:19:17 +01001957 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001958 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001959 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001960 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001961 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001962 curproxy->uri_auth = defproxy.uri_auth;
1963 curproxy->mon_net = defproxy.mon_net;
1964 curproxy->mon_mask = defproxy.mon_mask;
1965 if (defproxy.monitor_uri)
1966 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1967 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001968 if (defproxy.defbe.name)
1969 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001970
1971 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001972 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1973 if (curproxy->conf.logformat_string &&
1974 curproxy->conf.logformat_string != default_http_log_format &&
1975 curproxy->conf.logformat_string != default_tcp_log_format &&
1976 curproxy->conf.logformat_string != clf_http_log_format)
1977 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1978
1979 if (defproxy.conf.lfs_file) {
1980 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1981 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1982 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001983 }
1984
1985 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001986 curproxy->timeout.connect = defproxy.timeout.connect;
1987 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001988 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001989 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001990 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001991 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001992 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001993 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001994 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001995 }
1996
Willy Tarreaubaaee002006-06-26 02:48:02 +02001997 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001998
1999 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002000 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002001 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002002 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002003 LIST_INIT(&node->list);
2004 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2005 }
2006
Willy Tarreau62a61232013-04-12 18:13:46 +02002007 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2008 if (curproxy->conf.uniqueid_format_string)
2009 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2010
2011 if (defproxy.conf.uif_file) {
2012 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2013 curproxy->conf.uif_line = defproxy.conf.uif_line;
2014 }
William Lallemanda73203e2012-03-12 12:48:57 +01002015
2016 /* copy default header unique id */
2017 if (defproxy.header_unique_id)
2018 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2019
William Lallemand82fe75c2012-10-23 10:25:10 +02002020 /* default compression options */
2021 if (defproxy.comp != NULL) {
2022 curproxy->comp = calloc(1, sizeof(struct comp));
2023 curproxy->comp->algos = defproxy.comp->algos;
2024 curproxy->comp->types = defproxy.comp->types;
2025 }
2026
Willy Tarreaubaaee002006-06-26 02:48:02 +02002027 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002028 curproxy->conf.used_listener_id = EB_ROOT;
2029 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002030
Willy Tarreau93893792009-07-23 13:19:11 +02002031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032 }
2033 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2034 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002035 /* FIXME-20070101: we should do this too at the end of the
2036 * config parsing to free all default values.
2037 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002038 free(defproxy.check_req);
2039 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002040 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002041 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002042 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002043 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002044 free(defproxy.capture_name);
2045 free(defproxy.monitor_uri);
2046 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002047 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002048 free(defproxy.fwdfor_hdr_name);
2049 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002050 free(defproxy.orgto_hdr_name);
2051 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002052 free(defproxy.server_id_hdr_name);
2053 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002054 free(defproxy.expect_str);
2055 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002056
Willy Tarreau62a61232013-04-12 18:13:46 +02002057 if (defproxy.conf.logformat_string != default_http_log_format &&
2058 defproxy.conf.logformat_string != default_tcp_log_format &&
2059 defproxy.conf.logformat_string != clf_http_log_format)
2060 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002061
Willy Tarreau62a61232013-04-12 18:13:46 +02002062 free(defproxy.conf.uniqueid_format_string);
2063 free(defproxy.conf.lfs_file);
2064 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002065
Willy Tarreaua534fea2008-08-03 12:19:50 +02002066 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002067 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002068
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 /* we cannot free uri_auth because it might already be used */
2070 init_default_instance();
2071 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002072 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2073 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002075 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 }
2077 else if (curproxy == NULL) {
2078 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002079 err_code |= ERR_ALERT | ERR_FATAL;
2080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002082
2083 /* update the current file and line being parsed */
2084 curproxy->conf.args.file = curproxy->conf.file;
2085 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086
2087 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002089 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002090 int cur_arg;
2091
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 if (curproxy == &defproxy) {
2093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002094 err_code |= ERR_ALERT | ERR_FATAL;
2095 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002097 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002098 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099
Willy Tarreau24709282013-03-10 21:32:12 +01002100 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002101 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002103 err_code |= ERR_ALERT | ERR_FATAL;
2104 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002105 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002106
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002107 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002108
2109 /* use default settings for unix sockets */
2110 bind_conf->ux.uid = global.unix_bind.ux.uid;
2111 bind_conf->ux.gid = global.unix_bind.ux.gid;
2112 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002113
2114 /* NOTE: the following line might create several listeners if there
2115 * are comma-separated IPs or port ranges. So all further processing
2116 * will have to be applied to all listeners created after last_listen.
2117 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002118 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2119 if (errmsg && *errmsg) {
2120 indent_msg(&errmsg, 2);
2121 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002122 }
2123 else
2124 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2125 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
2128 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002129
Willy Tarreau4348fad2012-09-20 16:48:07 +02002130 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2131 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002132 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002133 }
2134
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002135 cur_arg = 2;
2136 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002137 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002138 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002139 char *err;
2140
Willy Tarreau26982662012-09-12 23:17:10 +02002141 kw = bind_find_kw(args[cur_arg]);
2142 if (kw) {
2143 char *err = NULL;
2144 int code;
2145
2146 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002147 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2148 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002149 cur_arg += 1 + kw->skip ;
2150 err_code |= ERR_ALERT | ERR_FATAL;
2151 goto out;
2152 }
2153
Willy Tarreau4348fad2012-09-20 16:48:07 +02002154 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002155 err_code |= code;
2156
2157 if (code) {
2158 if (err && *err) {
2159 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002160 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002161 }
2162 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002163 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2164 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002165 if (code & ERR_FATAL) {
2166 free(err);
2167 cur_arg += 1 + kw->skip;
2168 goto out;
2169 }
2170 }
2171 free(err);
2172 cur_arg += 1 + kw->skip;
2173 continue;
2174 }
2175
Willy Tarreau8638f482012-09-18 18:01:17 +02002176 err = NULL;
2177 if (!bind_dumped) {
2178 bind_dump_kws(&err);
2179 indent_msg(&err, 4);
2180 bind_dumped = 1;
2181 }
2182
2183 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2184 file, linenum, args[0], args[1], args[cur_arg],
2185 err ? " Registered keywords :" : "", err ? err : "");
2186 free(err);
2187
Willy Tarreau93893792009-07-23 13:19:11 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002190 }
Willy Tarreau93893792009-07-23 13:19:11 +02002191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 }
2193 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2194 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2195 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002200 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002201 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 /* flush useless bits */
2204 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002207 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002208 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002209 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002210
Willy Tarreau1c47f852006-07-09 08:22:27 +02002211 if (!*args[1]) {
2212 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002216 }
2217
Willy Tarreaua534fea2008-08-03 12:19:50 +02002218 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002219 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002220 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002221 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002222 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2223
Willy Tarreau93893792009-07-23 13:19:11 +02002224 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002225 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2227 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2228 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2229 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2230 else {
2231 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002234 }
2235 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002236 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002237 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002238
2239 if (curproxy == &defproxy) {
2240 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2241 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002244 }
2245
2246 if (!*args[1]) {
2247 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002251 }
2252
2253 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002254 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002255
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002256 if (curproxy->uuid <= 0) {
2257 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002258 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002261 }
2262
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002263 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2264 if (node) {
2265 struct proxy *target = container_of(node, struct proxy, conf.id);
2266 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2267 file, linenum, proxy_type_str(curproxy), curproxy->id,
2268 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002273 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002274 else if (!strcmp(args[0], "description")) {
2275 int i, len=0;
2276 char *d;
2277
Cyril Bonté99ed3272010-01-24 23:29:44 +01002278 if (curproxy == &defproxy) {
2279 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2280 file, linenum, args[0]);
2281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
2283 }
2284
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002285 if (!*args[1]) {
2286 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2287 file, linenum, args[0]);
2288 return -1;
2289 }
2290
2291 for(i=1; *args[i]; i++)
2292 len += strlen(args[i])+1;
2293
2294 d = (char *)calloc(1, len);
2295 curproxy->desc = d;
2296
2297 d += sprintf(d, "%s", args[1]);
2298 for(i=2; *args[i]; i++)
2299 d += sprintf(d, " %s", args[i]);
2300
2301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002302 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2303 curproxy->state = PR_STSTOPPED;
2304 }
2305 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2306 curproxy->state = PR_STNEW;
2307 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002308 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2309 int cur_arg = 1;
2310 unsigned int set = 0;
2311
2312 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002313 unsigned int low, high;
2314
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002315 if (strcmp(args[cur_arg], "all") == 0) {
2316 set = 0;
2317 break;
2318 }
2319 else if (strcmp(args[cur_arg], "odd") == 0) {
2320 set |= 0x55555555;
2321 }
2322 else if (strcmp(args[cur_arg], "even") == 0) {
2323 set |= 0xAAAAAAAA;
2324 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002325 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002326 char *dash = strchr(args[cur_arg], '-');
2327
2328 low = high = str2uic(args[cur_arg]);
2329 if (dash)
2330 high = str2uic(dash + 1);
2331
2332 if (high < low) {
2333 unsigned int swap = low;
2334 low = high;
2335 high = swap;
2336 }
2337
2338 if (low < 1 || high > 32) {
2339 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002340 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002341 err_code |= ERR_ALERT | ERR_FATAL;
2342 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002343 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002344
2345 if (high > global.nbproc) {
2346 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2347 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002349 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002350 while (low <= high)
2351 set |= 1 << (low++ - 1);
2352 }
2353 else {
2354 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2355 file, linenum, args[0]);
2356 err_code |= ERR_ALERT | ERR_FATAL;
2357 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002358 }
2359 cur_arg++;
2360 }
2361 curproxy->bind_proc = set;
2362 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002363 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002364 if (curproxy == &defproxy) {
2365 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002368 }
2369
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002370 err = invalid_char(args[1]);
2371 if (err) {
2372 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2373 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002374 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002375 }
2376
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002377 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002378 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2379 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002380 err_code |= ERR_ALERT | ERR_FATAL;
2381 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002382 }
2383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2385 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386
Willy Tarreau977b8e42006-12-29 14:19:17 +01002387 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002389
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 if (*(args[1]) == 0) {
2391 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002396
Willy Tarreau67402132012-05-31 20:40:20 +02002397 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002398 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002399 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002400 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002401 curproxy->cookie_name = strdup(args[1]);
2402 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002403
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 cur_arg = 2;
2405 while (*(args[cur_arg])) {
2406 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002407 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }
2409 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002410 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002413 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414 }
2415 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002416 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 }
2418 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002419 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002421 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002422 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002423 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002425 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002427 else if (!strcmp(args[cur_arg], "httponly")) {
2428 curproxy->ck_opts |= PR_CK_HTTPONLY;
2429 }
2430 else if (!strcmp(args[cur_arg], "secure")) {
2431 curproxy->ck_opts |= PR_CK_SECURE;
2432 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002433 else if (!strcmp(args[cur_arg], "domain")) {
2434 if (!*args[cur_arg + 1]) {
2435 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2436 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002439 }
2440
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002441 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002442 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002443 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2444 " dots nor does not start with a dot."
2445 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002446 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002447 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002448 }
2449
2450 err = invalid_domainchar(args[cur_arg + 1]);
2451 if (err) {
2452 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2453 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002456 }
2457
Willy Tarreau68a897b2009-12-03 23:28:34 +01002458 if (!curproxy->cookie_domain) {
2459 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2460 } else {
2461 /* one domain was already specified, add another one by
2462 * building the string which will be returned along with
2463 * the cookie.
2464 */
2465 char *new_ptr;
2466 int new_len = strlen(curproxy->cookie_domain) +
2467 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2468 new_ptr = malloc(new_len);
2469 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2470 free(curproxy->cookie_domain);
2471 curproxy->cookie_domain = new_ptr;
2472 }
Willy Tarreau31936852010-10-06 16:59:56 +02002473 cur_arg++;
2474 }
2475 else if (!strcmp(args[cur_arg], "maxidle")) {
2476 unsigned int maxidle;
2477 const char *res;
2478
2479 if (!*args[cur_arg + 1]) {
2480 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2481 file, linenum, args[cur_arg]);
2482 err_code |= ERR_ALERT | ERR_FATAL;
2483 goto out;
2484 }
2485
2486 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2487 if (res) {
2488 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2489 file, linenum, *res, args[cur_arg]);
2490 err_code |= ERR_ALERT | ERR_FATAL;
2491 goto out;
2492 }
2493 curproxy->cookie_maxidle = maxidle;
2494 cur_arg++;
2495 }
2496 else if (!strcmp(args[cur_arg], "maxlife")) {
2497 unsigned int maxlife;
2498 const char *res;
2499
2500 if (!*args[cur_arg + 1]) {
2501 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2502 file, linenum, args[cur_arg]);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506
2507 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2508 if (res) {
2509 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2510 file, linenum, *res, args[cur_arg]);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002515 cur_arg++;
2516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002518 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002520 err_code |= ERR_ALERT | ERR_FATAL;
2521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 }
2523 cur_arg++;
2524 }
Willy Tarreau67402132012-05-31 20:40:20 +02002525 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2527 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002528 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 }
2530
Willy Tarreau67402132012-05-31 20:40:20 +02002531 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2533 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002536
Willy Tarreau67402132012-05-31 20:40:20 +02002537 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002538 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2539 file, linenum);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002543 else if (!strcmp(args[0], "persist")) { /* persist */
2544 if (*(args[1]) == 0) {
2545 Alert("parsing [%s:%d] : missing persist method.\n",
2546 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002547 err_code |= ERR_ALERT | ERR_FATAL;
2548 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002549 }
2550
2551 if (!strncmp(args[1], "rdp-cookie", 10)) {
2552 curproxy->options2 |= PR_O2_RDPC_PRST;
2553
Emeric Brunb982a3d2010-01-04 15:45:53 +01002554 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002555 const char *beg, *end;
2556
2557 beg = args[1] + 11;
2558 end = strchr(beg, ')');
2559
2560 if (!end || end == beg) {
2561 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2562 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002565 }
2566
2567 free(curproxy->rdp_cookie_name);
2568 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2569 curproxy->rdp_cookie_len = end-beg;
2570 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002571 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002572 free(curproxy->rdp_cookie_name);
2573 curproxy->rdp_cookie_name = strdup("msts");
2574 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2575 }
2576 else { /* syntax */
2577 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2578 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
2580 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002581 }
2582 }
2583 else {
2584 Alert("parsing [%s:%d] : unknown persist method.\n",
2585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002588 }
2589 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002591 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002593 if (curproxy == &defproxy) {
2594 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
Willy Tarreau977b8e42006-12-29 14:19:17 +01002599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002600 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002601
Willy Tarreaubaaee002006-06-26 02:48:02 +02002602 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002603 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 }
2608 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002609 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 curproxy->appsession_name = strdup(args[1]);
2611 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2612 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002613 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2614 if (err) {
2615 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2616 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002619 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002620 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002621
Willy Tarreau51041c72007-09-09 21:56:53 +02002622 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2623 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_ABORT;
2625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002627
2628 cur_arg = 6;
2629 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002630 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2631 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002632 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002633 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002634 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002635 } else if (!strcmp(args[cur_arg], "prefix")) {
2636 curproxy->options2 |= PR_O2_AS_PFX;
2637 } else if (!strcmp(args[cur_arg], "mode")) {
2638 if (!*args[cur_arg + 1]) {
2639 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2640 file, linenum, args[0], args[cur_arg]);
2641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
2643 }
2644
2645 cur_arg++;
2646 if (!strcmp(args[cur_arg], "query-string")) {
2647 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2648 curproxy->options2 |= PR_O2_AS_M_QS;
2649 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2650 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2651 curproxy->options2 |= PR_O2_AS_M_PP;
2652 } else {
2653 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002658 cur_arg++;
2659 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002660 } /* Url App Session */
2661 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002662 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002663 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002664
Willy Tarreaubaaee002006-06-26 02:48:02 +02002665 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002666 if (curproxy == &defproxy) {
2667 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 if (*(args[4]) == 0) {
2673 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002677 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002678 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 curproxy->capture_name = strdup(args[2]);
2680 curproxy->capture_namelen = strlen(curproxy->capture_name);
2681 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 curproxy->to_log |= LW_COOKIE;
2683 }
2684 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2685 struct cap_hdr *hdr;
2686
2687 if (curproxy == &defproxy) {
2688 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 }
2692
2693 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2694 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2695 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
2699
2700 hdr = calloc(sizeof(struct cap_hdr), 1);
2701 hdr->next = curproxy->req_cap;
2702 hdr->name = strdup(args[3]);
2703 hdr->namelen = strlen(args[3]);
2704 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002705 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002706 hdr->index = curproxy->nb_req_cap++;
2707 curproxy->req_cap = hdr;
2708 curproxy->to_log |= LW_REQHDR;
2709 }
2710 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2711 struct cap_hdr *hdr;
2712
2713 if (curproxy == &defproxy) {
2714 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002717 }
2718
2719 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2720 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2721 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 }
2725 hdr = calloc(sizeof(struct cap_hdr), 1);
2726 hdr->next = curproxy->rsp_cap;
2727 hdr->name = strdup(args[3]);
2728 hdr->namelen = strlen(args[3]);
2729 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002730 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 hdr->index = curproxy->nb_rsp_cap++;
2732 curproxy->rsp_cap = hdr;
2733 curproxy->to_log |= LW_RSPHDR;
2734 }
2735 else {
2736 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2737 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 }
2741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002744 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002745
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746 if (*(args[1]) == 0) {
2747 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2748 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002749 err_code |= ERR_ALERT | ERR_FATAL;
2750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 }
2752 curproxy->conn_retries = atol(args[1]);
2753 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002754 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002755 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002756
2757 if (curproxy == &defproxy) {
2758 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762
Willy Tarreau20b0de52012-12-24 15:45:22 +01002763 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2764 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2765 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2766 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002767 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002768 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2769 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002770 file, linenum, args[0]);
2771 err_code |= ERR_WARN;
2772 }
2773
Willy Tarreauff011f22011-01-06 17:51:27 +01002774 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002775
Willy Tarreauff011f22011-01-06 17:51:27 +01002776 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002777 err_code |= ERR_ALERT | ERR_ABORT;
2778 goto out;
2779 }
2780
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002781 err_code |= warnif_cond_conflicts(rule->cond,
2782 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2783 file, linenum);
2784
Willy Tarreauff011f22011-01-06 17:51:27 +01002785 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002786 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002787 else if (!strcmp(args[0], "http-response")) { /* response access control */
2788 struct http_res_rule *rule;
2789
2790 if (curproxy == &defproxy) {
2791 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
2794 }
2795
2796 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2797 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2798 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2799 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2800 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2801 file, linenum, args[0]);
2802 err_code |= ERR_WARN;
2803 }
2804
2805 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2806
2807 if (!rule) {
2808 err_code |= ERR_ALERT | ERR_ABORT;
2809 goto out;
2810 }
2811
2812 err_code |= warnif_cond_conflicts(rule->cond,
2813 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2814 file, linenum);
2815
2816 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2817 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002818 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2819 /* set the header name and length into the proxy structure */
2820 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2821 err_code |= ERR_WARN;
2822
2823 if (!*args[1]) {
2824 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2825 file, linenum, args[0]);
2826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
2828 }
2829
2830 /* set the desired header name */
2831 free(curproxy->server_id_hdr_name);
2832 curproxy->server_id_hdr_name = strdup(args[1]);
2833 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2834 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002835 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002836 if (curproxy == &defproxy) {
2837 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002840 }
2841
Willy Tarreauef6494c2010-01-28 17:12:36 +01002842 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002843 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2844 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002847 }
2848
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002849 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2850 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2851 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002854 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002855
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002856 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002857 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002858 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002859 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002860 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002861
Cyril Bonté99ed3272010-01-24 23:29:44 +01002862 if (curproxy == &defproxy) {
2863 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
2866 }
2867
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002868 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002869 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2870 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002873 }
2874
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002875 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002876 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002877 err_code |= warnif_cond_conflicts(rule->cond,
2878 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2879 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002880 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002881 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002882 struct switching_rule *rule;
2883
Willy Tarreaub099aca2008-10-12 17:26:37 +02002884 if (curproxy == &defproxy) {
2885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002886 err_code |= ERR_ALERT | ERR_FATAL;
2887 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002888 }
2889
Willy Tarreau55ea7572007-06-17 19:56:27 +02002890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002891 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002892
2893 if (*(args[1]) == 0) {
2894 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002897 }
2898
Willy Tarreauef6494c2010-01-28 17:12:36 +01002899 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002900 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2901 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002904 }
2905
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002906 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2907 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2908 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002911 }
2912
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002913 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002914
Willy Tarreau55ea7572007-06-17 19:56:27 +02002915 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2916 rule->cond = cond;
2917 rule->be.name = strdup(args[1]);
2918 LIST_INIT(&rule->list);
2919 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2920 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002921 else if (strcmp(args[0], "use-server") == 0) {
2922 struct server_rule *rule;
2923
2924 if (curproxy == &defproxy) {
2925 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2926 err_code |= ERR_ALERT | ERR_FATAL;
2927 goto out;
2928 }
2929
2930 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2931 err_code |= ERR_WARN;
2932
2933 if (*(args[1]) == 0) {
2934 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2935 err_code |= ERR_ALERT | ERR_FATAL;
2936 goto out;
2937 }
2938
2939 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2940 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2941 file, linenum, args[0]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002946 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2947 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2948 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002953 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002954
2955 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2956 rule->cond = cond;
2957 rule->srv.name = strdup(args[1]);
2958 LIST_INIT(&rule->list);
2959 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2960 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2961 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002962 else if ((!strcmp(args[0], "force-persist")) ||
2963 (!strcmp(args[0], "ignore-persist"))) {
2964 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002965
2966 if (curproxy == &defproxy) {
2967 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
2972 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2973 err_code |= ERR_WARN;
2974
Willy Tarreauef6494c2010-01-28 17:12:36 +01002975 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002976 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2977 file, linenum, args[0]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002982 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2983 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2984 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002989 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2990 * where force-persist is applied.
2991 */
2992 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002993
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002994 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002995 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002996 if (!strcmp(args[0], "force-persist")) {
2997 rule->type = PERSIST_TYPE_FORCE;
2998 } else {
2999 rule->type = PERSIST_TYPE_IGNORE;
3000 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003001 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003002 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003003 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 else if (!strcmp(args[0], "stick-table")) {
3005 int myidx = 1;
3006
Emeric Brun32da3c42010-09-23 18:39:19 +02003007 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003008 curproxy->table.type = (unsigned int)-1;
3009 while (*args[myidx]) {
3010 const char *err;
3011
3012 if (strcmp(args[myidx], "size") == 0) {
3013 myidx++;
3014 if (!*(args[myidx])) {
3015 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3016 file, linenum, args[myidx-1]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3021 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3022 file, linenum, *err, args[myidx-1]);
3023 err_code |= ERR_ALERT | ERR_FATAL;
3024 goto out;
3025 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003026 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003028 else if (strcmp(args[myidx], "peers") == 0) {
3029 myidx++;
Godbach50523162013-12-11 19:48:57 +08003030 if (!*(args[myidx])) {
3031 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3032 file, linenum, args[myidx-1]);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003036 curproxy->table.peers.name = strdup(args[myidx++]);
3037 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 else if (strcmp(args[myidx], "expire") == 0) {
3039 myidx++;
3040 if (!*(args[myidx])) {
3041 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3042 file, linenum, args[myidx-1]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3047 if (err) {
3048 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3049 file, linenum, *err, args[myidx-1]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003054 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003055 }
3056 else if (strcmp(args[myidx], "nopurge") == 0) {
3057 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003058 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003059 }
3060 else if (strcmp(args[myidx], "type") == 0) {
3061 myidx++;
3062 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3063 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3064 file, linenum, args[myidx]);
3065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
3067 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003068 /* myidx already points to next arg */
3069 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003070 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003071 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003072 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003073
3074 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003075 nw = args[myidx];
3076 while (*nw) {
3077 /* the "store" keyword supports a comma-separated list */
3078 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003079 sa = NULL; /* store arg */
3080 while (*nw && *nw != ',') {
3081 if (*nw == '(') {
3082 *nw = 0;
3083 sa = ++nw;
3084 while (*nw != ')') {
3085 if (!*nw) {
3086 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3087 file, linenum, args[0], cw);
3088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
3090 }
3091 nw++;
3092 }
3093 *nw = '\0';
3094 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003095 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003096 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003097 if (*nw)
3098 *nw++ = '\0';
3099 type = stktable_get_data_type(cw);
3100 if (type < 0) {
3101 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3102 file, linenum, args[0], cw);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
Willy Tarreauac782882010-06-20 10:41:54 +02003106
3107 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3108 switch (err) {
3109 case PE_NONE: break;
3110 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003111 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3112 file, linenum, args[0], cw);
3113 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003114 break;
3115
3116 case PE_ARG_MISSING:
3117 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3118 file, linenum, args[0], cw);
3119 err_code |= ERR_ALERT | ERR_FATAL;
3120 goto out;
3121
3122 case PE_ARG_NOT_USED:
3123 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3124 file, linenum, args[0], cw);
3125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
3127
3128 default:
3129 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3130 file, linenum, args[0], cw);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003133 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003134 }
3135 myidx++;
3136 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003137 else {
3138 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3139 file, linenum, args[myidx]);
3140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003142 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003143 }
3144
3145 if (!curproxy->table.size) {
3146 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3147 file, linenum);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151
3152 if (curproxy->table.type == (unsigned int)-1) {
3153 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3154 file, linenum);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158 }
3159 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003160 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003161 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 int myidx = 0;
3163 const char *name = NULL;
3164 int flags;
3165
3166 if (curproxy == &defproxy) {
3167 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3168 err_code |= ERR_ALERT | ERR_FATAL;
3169 goto out;
3170 }
3171
3172 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3173 err_code |= ERR_WARN;
3174 goto out;
3175 }
3176
3177 myidx++;
3178 if ((strcmp(args[myidx], "store") == 0) ||
3179 (strcmp(args[myidx], "store-request") == 0)) {
3180 myidx++;
3181 flags = STK_IS_STORE;
3182 }
3183 else if (strcmp(args[myidx], "store-response") == 0) {
3184 myidx++;
3185 flags = STK_IS_STORE | STK_ON_RSP;
3186 }
3187 else if (strcmp(args[myidx], "match") == 0) {
3188 myidx++;
3189 flags = STK_IS_MATCH;
3190 }
3191 else if (strcmp(args[myidx], "on") == 0) {
3192 myidx++;
3193 flags = STK_IS_MATCH | STK_IS_STORE;
3194 }
3195 else {
3196 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
3199 }
3200
3201 if (*(args[myidx]) == 0) {
3202 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003207 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003208 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003209 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003210 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214
3215 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003216 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3217 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3218 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003219 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003220 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003221 goto out;
3222 }
3223 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003224 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3225 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3226 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003227 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003228 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003229 goto out;
3230 }
3231 }
3232
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003233 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003234 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003235
Emeric Brunb982a3d2010-01-04 15:45:53 +01003236 if (strcmp(args[myidx], "table") == 0) {
3237 myidx++;
3238 name = args[myidx++];
3239 }
3240
Willy Tarreauef6494c2010-01-28 17:12:36 +01003241 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003242 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3243 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3244 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003245 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003246 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003247 goto out;
3248 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003250 else if (*(args[myidx])) {
3251 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3252 file, linenum, args[0], args[myidx]);
3253 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003254 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003255 goto out;
3256 }
Emeric Brun97679e72010-09-23 17:56:44 +02003257 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003258 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003259 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003260 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003261
Emeric Brunb982a3d2010-01-04 15:45:53 +01003262 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3263 rule->cond = cond;
3264 rule->expr = expr;
3265 rule->flags = flags;
3266 rule->table.name = name ? strdup(name) : NULL;
3267 LIST_INIT(&rule->list);
3268 if (flags & STK_ON_RSP)
3269 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3270 else
3271 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003273 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003274 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003275 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003276
Willy Tarreaubaaee002006-06-26 02:48:02 +02003277 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3278 curproxy->uri_auth = NULL; /* we must detach from the default config */
3279
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003280 if (!*args[1]) {
3281 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003282 } else if (!strcmp(args[1], "admin")) {
3283 struct stats_admin_rule *rule;
3284
3285 if (curproxy == &defproxy) {
3286 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
3289 }
3290
3291 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3292 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3293 err_code |= ERR_ALERT | ERR_ABORT;
3294 goto out;
3295 }
3296
3297 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3298 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3299 file, linenum, args[0], args[1]);
3300 err_code |= ERR_ALERT | ERR_FATAL;
3301 goto out;
3302 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003303 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3304 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3305 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003306 err_code |= ERR_ALERT | ERR_FATAL;
3307 goto out;
3308 }
3309
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003310 err_code |= warnif_cond_conflicts(cond,
3311 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3312 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003313
3314 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3315 rule->cond = cond;
3316 LIST_INIT(&rule->list);
3317 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 } else if (!strcmp(args[1], "uri")) {
3319 if (*(args[2]) == 0) {
3320 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003321 err_code |= ERR_ALERT | ERR_FATAL;
3322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3324 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_ABORT;
3326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327 }
3328 } else if (!strcmp(args[1], "realm")) {
3329 if (*(args[2]) == 0) {
3330 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3334 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003335 err_code |= ERR_ALERT | ERR_ABORT;
3336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003338 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003339 unsigned interval;
3340
3341 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3342 if (err) {
3343 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3344 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003347 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3348 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_ABORT;
3350 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003351 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003352 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003353 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003354
3355 if (curproxy == &defproxy) {
3356 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360
3361 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3362 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3363 err_code |= ERR_ALERT | ERR_ABORT;
3364 goto out;
3365 }
3366
Willy Tarreauff011f22011-01-06 17:51:27 +01003367 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3368 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003369 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3370 file, linenum, args[0]);
3371 err_code |= ERR_WARN;
3372 }
3373
Willy Tarreauff011f22011-01-06 17:51:27 +01003374 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003375
Willy Tarreauff011f22011-01-06 17:51:27 +01003376 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003377 err_code |= ERR_ALERT | ERR_ABORT;
3378 goto out;
3379 }
3380
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003381 err_code |= warnif_cond_conflicts(rule->cond,
3382 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3383 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003384 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003385
Willy Tarreaubaaee002006-06-26 02:48:02 +02003386 } else if (!strcmp(args[1], "auth")) {
3387 if (*(args[2]) == 0) {
3388 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3392 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003393 err_code |= ERR_ALERT | ERR_ABORT;
3394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003395 }
3396 } else if (!strcmp(args[1], "scope")) {
3397 if (*(args[2]) == 0) {
3398 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3402 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_ABORT;
3404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
3406 } else if (!strcmp(args[1], "enable")) {
3407 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003409 err_code |= ERR_ALERT | ERR_ABORT;
3410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003412 } else if (!strcmp(args[1], "hide-version")) {
3413 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3414 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_ALERT | ERR_ABORT;
3416 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003417 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003418 } else if (!strcmp(args[1], "show-legends")) {
3419 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3420 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3421 err_code |= ERR_ALERT | ERR_ABORT;
3422 goto out;
3423 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003424 } else if (!strcmp(args[1], "show-node")) {
3425
3426 if (*args[2]) {
3427 int i;
3428 char c;
3429
3430 for (i=0; args[2][i]; i++) {
3431 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003432 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3433 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003434 break;
3435 }
3436
3437 if (!i || args[2][i]) {
3438 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3439 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3440 file, linenum, args[0], args[1]);
3441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444 }
3445
3446 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3447 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3448 err_code |= ERR_ALERT | ERR_ABORT;
3449 goto out;
3450 }
3451 } else if (!strcmp(args[1], "show-desc")) {
3452 char *desc = NULL;
3453
3454 if (*args[2]) {
3455 int i, len=0;
3456 char *d;
3457
3458 for(i=2; *args[i]; i++)
3459 len += strlen(args[i])+1;
3460
3461 desc = d = (char *)calloc(1, len);
3462
3463 d += sprintf(d, "%s", args[2]);
3464 for(i=3; *args[i]; i++)
3465 d += sprintf(d, " %s", args[i]);
3466 }
3467
3468 if (!*args[2] && !global.desc)
3469 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3470 file, linenum, args[1]);
3471 else {
3472 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3473 free(desc);
3474 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3475 err_code |= ERR_ALERT | ERR_ABORT;
3476 goto out;
3477 }
3478 free(desc);
3479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003481stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003482 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003483 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
3487 }
3488 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003489 int optnum;
3490
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003491 if (*(args[1]) == '\0') {
3492 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3493 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003494 err_code |= ERR_ALERT | ERR_FATAL;
3495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003497
3498 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3499 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003500 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3501 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3502 file, linenum, cfg_opts[optnum].name);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
Willy Tarreau93893792009-07-23 13:19:11 +02003506 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3507 err_code |= ERR_WARN;
3508 goto out;
3509 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003510
Willy Tarreau3842f002009-06-14 11:39:52 +02003511 curproxy->no_options &= ~cfg_opts[optnum].val;
3512 curproxy->options &= ~cfg_opts[optnum].val;
3513
3514 switch (kwm) {
3515 case KWM_STD:
3516 curproxy->options |= cfg_opts[optnum].val;
3517 break;
3518 case KWM_NO:
3519 curproxy->no_options |= cfg_opts[optnum].val;
3520 break;
3521 case KWM_DEF: /* already cleared */
3522 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003523 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003524
Willy Tarreau93893792009-07-23 13:19:11 +02003525 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003526 }
3527 }
3528
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003529 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3530 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003531 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3532 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3533 file, linenum, cfg_opts2[optnum].name);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
Willy Tarreau93893792009-07-23 13:19:11 +02003537 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3538 err_code |= ERR_WARN;
3539 goto out;
3540 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003541
Willy Tarreau3842f002009-06-14 11:39:52 +02003542 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3543 curproxy->options2 &= ~cfg_opts2[optnum].val;
3544
3545 switch (kwm) {
3546 case KWM_STD:
3547 curproxy->options2 |= cfg_opts2[optnum].val;
3548 break;
3549 case KWM_NO:
3550 curproxy->no_options2 |= cfg_opts2[optnum].val;
3551 break;
3552 case KWM_DEF: /* already cleared */
3553 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003554 }
Willy Tarreau93893792009-07-23 13:19:11 +02003555 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003556 }
3557 }
3558
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003559 /* HTTP options override each other. They can be cancelled using
3560 * "no option xxx" which only switches to default mode if the mode
3561 * was this one (useful for cancelling options set in defaults
3562 * sections).
3563 */
3564 if (strcmp(args[1], "httpclose") == 0) {
3565 if (kwm == KWM_STD) {
3566 curproxy->options &= ~PR_O_HTTP_MODE;
3567 curproxy->options |= PR_O_HTTP_PCL;
3568 goto out;
3569 }
3570 else if (kwm == KWM_NO) {
3571 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3572 curproxy->options &= ~PR_O_HTTP_MODE;
3573 goto out;
3574 }
3575 }
3576 else if (strcmp(args[1], "forceclose") == 0) {
3577 if (kwm == KWM_STD) {
3578 curproxy->options &= ~PR_O_HTTP_MODE;
3579 curproxy->options |= PR_O_HTTP_FCL;
3580 goto out;
3581 }
3582 else if (kwm == KWM_NO) {
3583 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3584 curproxy->options &= ~PR_O_HTTP_MODE;
3585 goto out;
3586 }
3587 }
3588 else if (strcmp(args[1], "http-server-close") == 0) {
3589 if (kwm == KWM_STD) {
3590 curproxy->options &= ~PR_O_HTTP_MODE;
3591 curproxy->options |= PR_O_HTTP_SCL;
3592 goto out;
3593 }
3594 else if (kwm == KWM_NO) {
3595 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3596 curproxy->options &= ~PR_O_HTTP_MODE;
3597 goto out;
3598 }
3599 }
3600 else if (strcmp(args[1], "http-keep-alive") == 0) {
3601 if (kwm == KWM_STD) {
3602 curproxy->options &= ~PR_O_HTTP_MODE;
3603 curproxy->options |= PR_O_HTTP_KAL;
3604 goto out;
3605 }
3606 else if (kwm == KWM_NO) {
3607 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3608 curproxy->options &= ~PR_O_HTTP_MODE;
3609 goto out;
3610 }
3611 }
3612 else if (strcmp(args[1], "http-tunnel") == 0) {
3613 if (kwm == KWM_STD) {
3614 curproxy->options &= ~PR_O_HTTP_MODE;
3615 curproxy->options |= PR_O_HTTP_TUN;
3616 goto out;
3617 }
3618 else if (kwm == KWM_NO) {
3619 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3620 curproxy->options &= ~PR_O_HTTP_MODE;
3621 goto out;
3622 }
3623 }
3624
Willy Tarreau3842f002009-06-14 11:39:52 +02003625 if (kwm != KWM_STD) {
3626 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003627 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003628 err_code |= ERR_ALERT | ERR_FATAL;
3629 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003630 }
3631
Emeric Brun3a058f32009-06-30 18:26:00 +02003632 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003633 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003635 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003636 if (*(args[2]) != '\0') {
3637 if (!strcmp(args[2], "clf")) {
3638 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003639 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003640 } else {
3641 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003644 }
3645 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003646 if (curproxy->conf.logformat_string != default_http_log_format &&
3647 curproxy->conf.logformat_string != default_tcp_log_format &&
3648 curproxy->conf.logformat_string != clf_http_log_format)
3649 free(curproxy->conf.logformat_string);
3650 curproxy->conf.logformat_string = logformat;
3651
3652 free(curproxy->conf.lfs_file);
3653 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3654 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003655 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003656 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003658 if (curproxy->conf.logformat_string != default_http_log_format &&
3659 curproxy->conf.logformat_string != default_tcp_log_format &&
3660 curproxy->conf.logformat_string != clf_http_log_format)
3661 free(curproxy->conf.logformat_string);
3662 curproxy->conf.logformat_string = default_tcp_log_format;
3663
3664 free(curproxy->conf.lfs_file);
3665 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3666 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 else if (!strcmp(args[1], "tcpka")) {
3669 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003670 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003671 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003672
3673 if (curproxy->cap & PR_CAP_FE)
3674 curproxy->options |= PR_O_TCP_CLI_KA;
3675 if (curproxy->cap & PR_CAP_BE)
3676 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003677 }
3678 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003679 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003680 err_code |= ERR_WARN;
3681
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003683 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003684 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003685 curproxy->options2 &= ~PR_O2_CHK_ANY;
3686 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 if (!*args[2]) { /* no argument */
3688 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3689 curproxy->check_len = strlen(DEF_CHECK_REQ);
3690 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003691 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003692 curproxy->check_req = (char *)malloc(reqlen);
3693 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003694 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003695 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003696 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 if (*args[4])
3698 reqlen += strlen(args[4]);
3699 else
3700 reqlen += strlen("HTTP/1.0");
3701
3702 curproxy->check_req = (char *)malloc(reqlen);
3703 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003704 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003706 }
3707 else if (!strcmp(args[1], "ssl-hello-chk")) {
3708 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003709 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003710 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003711
Willy Tarreaua534fea2008-08-03 12:19:50 +02003712 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003713 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003714 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003715 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003716 }
Willy Tarreau23677902007-05-08 23:50:35 +02003717 else if (!strcmp(args[1], "smtpchk")) {
3718 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003719 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003720 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003721 curproxy->options2 &= ~PR_O2_CHK_ANY;
3722 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003723
3724 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3725 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3726 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3727 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3728 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3729 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3730 curproxy->check_req = (char *)malloc(reqlen);
3731 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3732 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3733 } else {
3734 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3735 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3736 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3737 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3738 }
3739 }
3740 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003741 else if (!strcmp(args[1], "pgsql-check")) {
3742 /* use PostgreSQL request to check servers' health */
3743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3744 err_code |= ERR_WARN;
3745
3746 free(curproxy->check_req);
3747 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003748 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003749 curproxy->options2 |= PR_O2_PGSQL_CHK;
3750
3751 if (*(args[2])) {
3752 int cur_arg = 2;
3753
3754 while (*(args[cur_arg])) {
3755 if (strcmp(args[cur_arg], "user") == 0) {
3756 char * packet;
3757 uint32_t packet_len;
3758 uint32_t pv;
3759
3760 /* suboption header - needs additional argument for it */
3761 if (*(args[cur_arg+1]) == 0) {
3762 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3763 file, linenum, args[0], args[1], args[cur_arg]);
3764 err_code |= ERR_ALERT | ERR_FATAL;
3765 goto out;
3766 }
3767
3768 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3769 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3770 pv = htonl(0x30000); /* protocol version 3.0 */
3771
3772 packet = (char*) calloc(1, packet_len);
3773
3774 memcpy(packet + 4, &pv, 4);
3775
3776 /* copy "user" */
3777 memcpy(packet + 8, "user", 4);
3778
3779 /* copy username */
3780 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3781
3782 free(curproxy->check_req);
3783 curproxy->check_req = packet;
3784 curproxy->check_len = packet_len;
3785
3786 packet_len = htonl(packet_len);
3787 memcpy(packet, &packet_len, 4);
3788 cur_arg += 2;
3789 } else {
3790 /* unknown suboption - catchall */
3791 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3792 file, linenum, args[0], args[1]);
3793 err_code |= ERR_ALERT | ERR_FATAL;
3794 goto out;
3795 }
3796 } /* end while loop */
3797 }
3798 }
3799
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003800 else if (!strcmp(args[1], "redis-check")) {
3801 /* use REDIS PING request to check servers' health */
3802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3803 err_code |= ERR_WARN;
3804
3805 free(curproxy->check_req);
3806 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003807 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003808 curproxy->options2 |= PR_O2_REDIS_CHK;
3809
3810 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3811 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3812 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3813 }
3814
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003815 else if (!strcmp(args[1], "mysql-check")) {
3816 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003817 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3818 err_code |= ERR_WARN;
3819
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003820 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003821 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003822 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003823 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003824
3825 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3826 * const char mysql40_client_auth_pkt[] = {
3827 * "\x0e\x00\x00" // packet length
3828 * "\x01" // packet number
3829 * "\x00\x00" // client capabilities
3830 * "\x00\x00\x01" // max packet
3831 * "haproxy\x00" // username (null terminated string)
3832 * "\x00" // filler (always 0x00)
3833 * "\x01\x00\x00" // packet length
3834 * "\x00" // packet number
3835 * "\x01" // COM_QUIT command
3836 * };
3837 */
3838
3839 if (*(args[2])) {
3840 int cur_arg = 2;
3841
3842 while (*(args[cur_arg])) {
3843 if (strcmp(args[cur_arg], "user") == 0) {
3844 char *mysqluser;
3845 int packetlen, reqlen, userlen;
3846
3847 /* suboption header - needs additional argument for it */
3848 if (*(args[cur_arg+1]) == 0) {
3849 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3850 file, linenum, args[0], args[1], args[cur_arg]);
3851 err_code |= ERR_ALERT | ERR_FATAL;
3852 goto out;
3853 }
3854 mysqluser = args[cur_arg + 1];
3855 userlen = strlen(mysqluser);
3856 packetlen = userlen + 7;
3857 reqlen = packetlen + 9;
3858
3859 free(curproxy->check_req);
3860 curproxy->check_req = (char *)calloc(1, reqlen);
3861 curproxy->check_len = reqlen;
3862
3863 snprintf(curproxy->check_req, 4, "%c%c%c",
3864 ((unsigned char) packetlen & 0xff),
3865 ((unsigned char) (packetlen >> 8) & 0xff),
3866 ((unsigned char) (packetlen >> 16) & 0xff));
3867
3868 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003869 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003870 curproxy->check_req[8] = 1;
3871 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3872 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3873 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3874 cur_arg += 2;
3875 } else {
3876 /* unknown suboption - catchall */
3877 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3878 file, linenum, args[0], args[1]);
3879 err_code |= ERR_ALERT | ERR_FATAL;
3880 goto out;
3881 }
3882 } /* end while loop */
3883 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003884 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003885 else if (!strcmp(args[1], "ldap-check")) {
3886 /* use LDAP request to check servers' health */
3887 free(curproxy->check_req);
3888 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003889 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003890 curproxy->options2 |= PR_O2_LDAP_CHK;
3891
3892 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3893 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3894 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3895 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003896 else if (!strcmp(args[1], "tcp-check")) {
3897 /* use raw TCPCHK send/expect to check servers' health */
3898 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3899 err_code |= ERR_WARN;
3900
3901 free(curproxy->check_req);
3902 curproxy->check_req = NULL;
3903 curproxy->options2 &= ~PR_O2_CHK_ANY;
3904 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3905 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003906 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003907 int cur_arg;
3908
3909 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3910 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003911 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003912
Willy Tarreau87cf5142011-08-19 22:57:24 +02003913 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003914
3915 free(curproxy->fwdfor_hdr_name);
3916 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3917 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3918
3919 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3920 cur_arg = 2;
3921 while (*(args[cur_arg])) {
3922 if (!strcmp(args[cur_arg], "except")) {
3923 /* suboption except - needs additional argument for it */
3924 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3925 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3926 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003929 }
3930 /* flush useless bits */
3931 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003932 cur_arg += 2;
3933 } else if (!strcmp(args[cur_arg], "header")) {
3934 /* suboption header - needs additional argument for it */
3935 if (*(args[cur_arg+1]) == 0) {
3936 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3937 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003940 }
3941 free(curproxy->fwdfor_hdr_name);
3942 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3943 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3944 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003945 } else if (!strcmp(args[cur_arg], "if-none")) {
3946 curproxy->options &= ~PR_O_FF_ALWAYS;
3947 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003948 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003949 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003950 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003951 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003954 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003955 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003956 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003957 else if (!strcmp(args[1], "originalto")) {
3958 int cur_arg;
3959
3960 /* insert x-original-to field, but not for the IP address listed as an except.
3961 * set default options (ie: bitfield, header name, etc)
3962 */
3963
3964 curproxy->options |= PR_O_ORGTO;
3965
3966 free(curproxy->orgto_hdr_name);
3967 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3968 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3969
Willy Tarreau87cf5142011-08-19 22:57:24 +02003970 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003971 cur_arg = 2;
3972 while (*(args[cur_arg])) {
3973 if (!strcmp(args[cur_arg], "except")) {
3974 /* suboption except - needs additional argument for it */
3975 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3976 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3977 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003980 }
3981 /* flush useless bits */
3982 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3983 cur_arg += 2;
3984 } else if (!strcmp(args[cur_arg], "header")) {
3985 /* suboption header - needs additional argument for it */
3986 if (*(args[cur_arg+1]) == 0) {
3987 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3988 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_ALERT | ERR_FATAL;
3990 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003991 }
3992 free(curproxy->orgto_hdr_name);
3993 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3994 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3995 cur_arg += 2;
3996 } else {
3997 /* unknown suboption - catchall */
3998 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3999 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004002 }
4003 } /* end while loop */
4004 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004005 else {
4006 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004009 }
Willy Tarreau93893792009-07-23 13:19:11 +02004010 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004011 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004012 else if (!strcmp(args[0], "default_backend")) {
4013 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004015
4016 if (*(args[1]) == 0) {
4017 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004020 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004021 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004022 curproxy->defbe.name = strdup(args[1]);
4023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004024 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004025 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004026 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004027
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004028 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4029 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004030 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 /* enable reconnections to dispatch */
4032 curproxy->options |= PR_O_REDISP;
4033 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004034 else if (!strcmp(args[0], "http-check")) {
4035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004036 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004037
4038 if (strcmp(args[1], "disable-on-404") == 0) {
4039 /* enable a graceful server shutdown on an HTTP 404 response */
4040 curproxy->options |= PR_O_DISABLE404;
4041 }
Willy Tarreauef781042010-01-27 11:53:01 +01004042 else if (strcmp(args[1], "send-state") == 0) {
4043 /* enable emission of the apparent state of a server in HTTP checks */
4044 curproxy->options2 |= PR_O2_CHK_SNDST;
4045 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004046 else if (strcmp(args[1], "expect") == 0) {
4047 const char *ptr_arg;
4048 int cur_arg;
4049
4050 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4051 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055
4056 cur_arg = 2;
4057 /* consider exclamation marks, sole or at the beginning of a word */
4058 while (*(ptr_arg = args[cur_arg])) {
4059 while (*ptr_arg == '!') {
4060 curproxy->options2 ^= PR_O2_EXP_INV;
4061 ptr_arg++;
4062 }
4063 if (*ptr_arg)
4064 break;
4065 cur_arg++;
4066 }
4067 /* now ptr_arg points to the beginning of a word past any possible
4068 * exclamation mark, and cur_arg is the argument which holds this word.
4069 */
4070 if (strcmp(ptr_arg, "status") == 0) {
4071 if (!*(args[cur_arg + 1])) {
4072 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4073 file, linenum, args[0], args[1], ptr_arg);
4074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004078 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004079 curproxy->expect_str = strdup(args[cur_arg + 1]);
4080 }
4081 else if (strcmp(ptr_arg, "string") == 0) {
4082 if (!*(args[cur_arg + 1])) {
4083 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4084 file, linenum, args[0], args[1], ptr_arg);
4085 err_code |= ERR_ALERT | ERR_FATAL;
4086 goto out;
4087 }
4088 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004089 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004090 curproxy->expect_str = strdup(args[cur_arg + 1]);
4091 }
4092 else if (strcmp(ptr_arg, "rstatus") == 0) {
4093 if (!*(args[cur_arg + 1])) {
4094 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4095 file, linenum, args[0], args[1], ptr_arg);
4096 err_code |= ERR_ALERT | ERR_FATAL;
4097 goto out;
4098 }
4099 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004100 free(curproxy->expect_str);
4101 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4102 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004103 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4104 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4105 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4106 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4107 err_code |= ERR_ALERT | ERR_FATAL;
4108 goto out;
4109 }
4110 }
4111 else if (strcmp(ptr_arg, "rstring") == 0) {
4112 if (!*(args[cur_arg + 1])) {
4113 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4114 file, linenum, args[0], args[1], ptr_arg);
4115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
4117 }
4118 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004119 free(curproxy->expect_str);
4120 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4121 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004122 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4123 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4124 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4125 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128 }
4129 }
4130 else {
4131 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4132 file, linenum, args[0], args[1], ptr_arg);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004137 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004138 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004141 }
4142 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004143 else if (!strcmp(args[0], "tcp-check")) {
4144 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4145 err_code |= ERR_WARN;
4146
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004147 if (strcmp(args[1], "connect") == 0) {
4148 const char *ptr_arg;
4149 int cur_arg;
4150 struct tcpcheck_rule *tcpcheck;
4151 struct list *l;
4152
4153 /* check if first rule is also a 'connect' action */
4154 l = (struct list *)&curproxy->tcpcheck_rules;
4155 if (l->p != l->n) {
4156 tcpcheck = (struct tcpcheck_rule *)l->n;
4157 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4158 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4159 file, linenum);
4160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
4162 }
4163 }
4164
4165 cur_arg = 2;
4166 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4167 tcpcheck->action = TCPCHK_ACT_CONNECT;
4168
4169 /* parsing each parameters to fill up the rule */
4170 while (*(ptr_arg = args[cur_arg])) {
4171 /* tcp port */
4172 if (strcmp(args[cur_arg], "port") == 0) {
4173 if ( (atol(args[cur_arg + 1]) > 65535) ||
4174 (atol(args[cur_arg + 1]) < 1) ){
4175 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4176 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
4180 tcpcheck->port = atol(args[cur_arg + 1]);
4181 cur_arg += 2;
4182 }
4183 /* send proxy protocol */
4184 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4185 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4186 cur_arg++;
4187 }
4188#ifdef USE_OPENSSL
4189 else if (strcmp(args[cur_arg], "ssl") == 0) {
4190 curproxy->options |= PR_O_TCPCHK_SSL;
4191 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4192 cur_arg++;
4193 }
4194#endif /* USE_OPENSSL */
4195 else {
4196#ifdef USE_OPENSSL
4197 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4198#else /* USE_OPENSSL */
4199 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4200#endif /* USE_OPENSSL */
4201 file, linenum, args[0], args[1], args[cur_arg]);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
4205
4206 }
4207
4208 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4209 }
4210 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004211 if (! *(args[2]) ) {
4212 /* SEND string expected */
4213 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4214 file, linenum, args[0], args[1], args[2]);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217 } else {
4218 struct tcpcheck_rule *tcpcheck;
4219
4220 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4221
4222 tcpcheck->action = TCPCHK_ACT_SEND;
4223 tcpcheck->string_len = strlen(args[2]);
4224 tcpcheck->string = strdup(args[2]);
4225 tcpcheck->expect_regex = NULL;
4226
4227 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4228 }
4229 }
4230 else if (strcmp(args[1], "send-binary") == 0) {
4231 if (! *(args[2]) ) {
4232 /* SEND binary string expected */
4233 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4234 file, linenum, args[0], args[1], args[2]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 } else {
4238 struct tcpcheck_rule *tcpcheck;
4239 char *err = NULL;
4240
4241 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4242
4243 tcpcheck->action = TCPCHK_ACT_SEND;
4244 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4245 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4246 file, linenum, args[0], args[1], args[2], err);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250 tcpcheck->expect_regex = NULL;
4251
4252 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4253 }
4254 }
4255 else if (strcmp(args[1], "expect") == 0) {
4256 const char *ptr_arg;
4257 int cur_arg;
4258 int inverse = 0;
4259
4260 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4261 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
4264 }
4265
4266 cur_arg = 2;
4267 /* consider exclamation marks, sole or at the beginning of a word */
4268 while (*(ptr_arg = args[cur_arg])) {
4269 while (*ptr_arg == '!') {
4270 inverse = !inverse;
4271 ptr_arg++;
4272 }
4273 if (*ptr_arg)
4274 break;
4275 cur_arg++;
4276 }
4277 /* now ptr_arg points to the beginning of a word past any possible
4278 * exclamation mark, and cur_arg is the argument which holds this word.
4279 */
4280 if (strcmp(ptr_arg, "binary") == 0) {
4281 if (!*(args[cur_arg + 1])) {
4282 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4283 file, linenum, args[0], args[1], ptr_arg);
4284 err_code |= ERR_ALERT | ERR_FATAL;
4285 goto out;
4286 }
4287 struct tcpcheck_rule *tcpcheck;
4288 char *err = NULL;
4289
4290 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4291
4292 tcpcheck->action = TCPCHK_ACT_EXPECT;
4293 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4294 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4295 file, linenum, args[0], args[1], args[2], err);
4296 err_code |= ERR_ALERT | ERR_FATAL;
4297 goto out;
4298 }
4299 tcpcheck->expect_regex = NULL;
4300 tcpcheck->inverse = inverse;
4301
4302 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4303 }
4304 else if (strcmp(ptr_arg, "string") == 0) {
4305 if (!*(args[cur_arg + 1])) {
4306 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4307 file, linenum, args[0], args[1], ptr_arg);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 struct tcpcheck_rule *tcpcheck;
4312
4313 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4314
4315 tcpcheck->action = TCPCHK_ACT_EXPECT;
4316 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4317 tcpcheck->string = strdup(args[cur_arg + 1]);
4318 tcpcheck->expect_regex = NULL;
4319 tcpcheck->inverse = inverse;
4320
4321 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4322 }
4323 else if (strcmp(ptr_arg, "rstring") == 0) {
4324 if (!*(args[cur_arg + 1])) {
4325 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4326 file, linenum, args[0], args[1], ptr_arg);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330 struct tcpcheck_rule *tcpcheck;
4331
4332 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4333
4334 tcpcheck->action = TCPCHK_ACT_EXPECT;
4335 tcpcheck->string_len = 0;
4336 tcpcheck->string = NULL;
4337 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4338 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4339 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4340 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4341 err_code |= ERR_ALERT | ERR_FATAL;
4342 goto out;
4343 }
4344 tcpcheck->inverse = inverse;
4345
4346 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4347 }
4348 else {
4349 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4350 file, linenum, args[0], args[1], ptr_arg);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354 }
4355 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004356 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004361 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004362 if (curproxy == &defproxy) {
4363 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004366 }
4367
Willy Tarreaub80c2302007-11-30 20:51:32 +01004368 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004369 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004370
4371 if (strcmp(args[1], "fail") == 0) {
4372 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004373 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004374 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4375 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_ALERT | ERR_FATAL;
4377 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004378 }
4379
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004380 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4381 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4382 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004385 }
4386 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4387 }
4388 else {
4389 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004392 }
4393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004394#ifdef TPROXY
4395 else if (!strcmp(args[0], "transparent")) {
4396 /* enable transparent proxy connections */
4397 curproxy->options |= PR_O_TRANSP;
4398 }
4399#endif
4400 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004401 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004402 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004403
Willy Tarreaubaaee002006-06-26 02:48:02 +02004404 if (*(args[1]) == 0) {
4405 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004408 }
4409 curproxy->maxconn = atol(args[1]);
4410 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004411 else if (!strcmp(args[0], "backlog")) { /* backlog */
4412 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004414
4415 if (*(args[1]) == 0) {
4416 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004417 err_code |= ERR_ALERT | ERR_FATAL;
4418 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004419 }
4420 curproxy->backlog = atol(args[1]);
4421 }
Willy Tarreau86034312006-12-29 00:10:33 +01004422 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004425
Willy Tarreau86034312006-12-29 00:10:33 +01004426 if (*(args[1]) == 0) {
4427 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004430 }
4431 curproxy->fullconn = atol(args[1]);
4432 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004433 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4434 if (*(args[1]) == 0) {
4435 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004438 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004439 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4440 if (err) {
4441 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4442 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004445 }
4446 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 }
4448 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004449 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004450 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004451 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004452
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453 if (curproxy == &defproxy) {
4454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004455 err_code |= ERR_ALERT | ERR_FATAL;
4456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004458 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004460
Willy Tarreau902636f2013-03-10 19:44:48 +01004461 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004462 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004463 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004464 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004465 goto out;
4466 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004467
4468 proto = protocol_by_family(sk->ss_family);
4469 if (!proto || !proto->connect) {
4470 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4471 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004472 err_code |= ERR_ALERT | ERR_FATAL;
4473 goto out;
4474 }
4475
4476 if (port1 != port2) {
4477 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4478 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004481 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004482
4483 if (!port1) {
4484 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4485 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
4488 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004489
Willy Tarreaud5191e72010-02-09 20:50:45 +01004490 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004491 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 }
4493 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004494 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004495 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004496
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004497 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4498 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004502 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004503 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004504 /**
4505 * The syntax for hash-type config element is
4506 * hash-type {map-based|consistent} [[<algo>] avalanche]
4507 *
4508 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4509 */
4510 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004511
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004512 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4513 err_code |= ERR_WARN;
4514
4515 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004516 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4517 }
4518 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004519 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4520 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004521 else if (strcmp(args[1], "avalanche") == 0) {
4522 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4523 err_code |= ERR_ALERT | ERR_FATAL;
4524 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004525 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004526 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004527 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004528 err_code |= ERR_ALERT | ERR_FATAL;
4529 goto out;
4530 }
Bhaskar98634f02013-10-29 23:30:51 -04004531
4532 /* set the hash function to use */
4533 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004534 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004535 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004536
4537 /* if consistent with no argument, then avalanche modifier is also applied */
4538 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4539 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004540 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004541 /* set the hash function */
4542 if (!strcmp(args[2], "sdbm")) {
4543 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4544 }
4545 else if (!strcmp(args[2], "djb2")) {
4546 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004547 } else if (!strcmp(args[2], "wt6")) {
4548 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004549 }
4550 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004551 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555
4556 /* set the hash modifier */
4557 if (!strcmp(args[3], "avalanche")) {
4558 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4559 }
4560 else if (*args[3]) {
4561 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4562 err_code |= ERR_ALERT | ERR_FATAL;
4563 goto out;
4564 }
Bhaskar98634f02013-10-29 23:30:51 -04004565 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004566 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004567 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004568 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004569 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004570 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004572 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004573 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004576 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004577 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579
4580 if (!*args[2]) {
4581 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004583 err_code |= ERR_ALERT | ERR_FATAL;
4584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004585 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004586
4587 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004588 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004589 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4590 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004591 err_code |= ERR_ALERT | ERR_FATAL;
4592 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004593 }
4594
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004595 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004596 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004597 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004598 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004599
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004600 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4601 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4602 err_code |= ERR_ALERT | ERR_ABORT;
4603 goto out;
4604 }
4605
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004606 /* the servers are linked backwards first */
4607 newsrv->next = curproxy->srv;
4608 curproxy->srv = newsrv;
4609 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004610 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004611 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004612
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004613 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004614 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004615 LIST_INIT(&newsrv->pendconns);
4616 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004617 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004618 newsrv->state = SRV_RUNNING; /* early server setup */
4619 newsrv->last_change = now.tv_sec;
4620 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004622 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004623 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004624 * - IP: => port=+0, relative
4625 * - IP:N => port=N, absolute
4626 * - IP:+N => port=+N, relative
4627 * - IP:-N => port=-N, relative
4628 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004629 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004630 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004631 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004632 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004633 goto out;
4634 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004635
4636 proto = protocol_by_family(sk->ss_family);
4637 if (!proto || !proto->connect) {
4638 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4639 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004640 err_code |= ERR_ALERT | ERR_FATAL;
4641 goto out;
4642 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004643
4644 if (!port1 || !port2) {
4645 /* no port specified, +offset, -offset */
4646 newsrv->state |= SRV_MAPPORTS;
4647 }
4648 else if (port1 != port2) {
4649 /* port range */
4650 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4651 file, linenum, args[0], args[1], args[2]);
4652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
4654 }
4655 else {
4656 /* used by checks */
4657 realport = port1;
4658 }
4659
Willy Tarreaud5191e72010-02-09 20:50:45 +01004660 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004661 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4662 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004663
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004664 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004665 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4666 file, linenum, newsrv->addr.ss_family, args[2]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004670
Simon Hormand60d6912013-11-25 10:46:36 +09004671 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004672 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004673 newsrv->check.inter = curproxy->defsrv.check.inter;
4674 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4675 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004676 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4677 newsrv->agent.port = curproxy->defsrv.agent.port;
4678 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4679 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4680 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004681 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4682 newsrv->minconn = curproxy->defsrv.minconn;
4683 newsrv->maxconn = curproxy->defsrv.maxconn;
4684 newsrv->slowstart = curproxy->defsrv.slowstart;
4685 newsrv->onerror = curproxy->defsrv.onerror;
Willy Tarreauabd03df2014-02-18 10:36:15 +01004686 newsrv->onmarkeddown = curproxy->defsrv.onmarkeddown;
4687 newsrv->onmarkedup = curproxy->defsrv.onmarkedup;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004688 newsrv->consecutive_errors_limit
4689 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004690#ifdef OPENSSL
4691 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4692#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004693 newsrv->uweight = newsrv->iweight
4694 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695
Simon Horman69d29f92013-02-23 15:14:19 +09004696 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004697 newsrv->check.rise = curproxy->defsrv.check.rise;
4698 newsrv->check.fall = curproxy->defsrv.check.fall;
4699 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004700 newsrv->check.server = newsrv;
4701
Simon Hormand60d6912013-11-25 10:46:36 +09004702 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004703 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4704 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4705 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004706 newsrv->agent.server = newsrv;
4707
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004708 cur_arg = 3;
4709 } else {
4710 newsrv = &curproxy->defsrv;
4711 cur_arg = 1;
4712 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004713
Willy Tarreaubaaee002006-06-26 02:48:02 +02004714 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004715 if (!strcmp(args[cur_arg], "agent-check")) {
4716 global.maxsock++;
4717 do_agent = 1;
4718 cur_arg += 1;
4719 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4720 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4721 if (err) {
4722 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4723 file, linenum, *err, newsrv->id);
4724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
4726 }
4727 if (val <= 0) {
4728 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4729 file, linenum, val, args[cur_arg], newsrv->id);
4730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
4732 }
4733 newsrv->agent.inter = val;
4734 cur_arg += 2;
4735 }
4736 else if (!strcmp(args[cur_arg], "agent-port")) {
4737 global.maxsock++;
4738 newsrv->agent.port = atol(args[cur_arg + 1]);
4739 cur_arg += 2;
4740 }
4741 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004742 newsrv->cookie = strdup(args[cur_arg + 1]);
4743 newsrv->cklen = strlen(args[cur_arg + 1]);
4744 cur_arg += 2;
4745 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004746 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004747 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4748 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4749 cur_arg += 2;
4750 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004752 if (!*args[cur_arg + 1]) {
4753 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4754 file, linenum, args[cur_arg]);
4755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
4757 }
4758
Simon Horman58c32972013-11-25 10:46:38 +09004759 newsrv->check.rise = atol(args[cur_arg + 1]);
4760 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004761 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4762 file, linenum, args[cur_arg]);
4763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
4765 }
4766
Simon Horman125d0992013-02-24 17:23:38 +09004767 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004768 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004769 cur_arg += 2;
4770 }
4771 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004772 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004773
4774 if (!*args[cur_arg + 1]) {
4775 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4776 file, linenum, args[cur_arg]);
4777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
4780
Simon Horman58c32972013-11-25 10:46:38 +09004781 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004782 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4783 file, linenum, args[cur_arg]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786 }
4787
Willy Tarreaubaaee002006-06-26 02:48:02 +02004788 cur_arg += 2;
4789 }
4790 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004791 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4792 if (err) {
4793 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4794 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004795 err_code |= ERR_ALERT | ERR_FATAL;
4796 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004797 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004798 if (val <= 0) {
4799 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4800 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004803 }
Simon Horman66183002013-02-23 10:16:43 +09004804 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004805 cur_arg += 2;
4806 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004807 else if (!strcmp(args[cur_arg], "fastinter")) {
4808 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4809 if (err) {
4810 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4811 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004812 err_code |= ERR_ALERT | ERR_FATAL;
4813 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004814 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004815 if (val <= 0) {
4816 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4817 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004818 err_code |= ERR_ALERT | ERR_FATAL;
4819 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004820 }
Simon Horman66183002013-02-23 10:16:43 +09004821 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004822 cur_arg += 2;
4823 }
4824 else if (!strcmp(args[cur_arg], "downinter")) {
4825 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4826 if (err) {
4827 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4828 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_ALERT | ERR_FATAL;
4830 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004831 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004832 if (val <= 0) {
4833 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4834 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004837 }
Simon Horman66183002013-02-23 10:16:43 +09004838 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004839 cur_arg += 2;
4840 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004841 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004842 struct sockaddr_storage *sk;
4843 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004844 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004845
Willy Tarreau902636f2013-03-10 19:44:48 +01004846 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004847 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004848 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004849 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004850 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004851 goto out;
4852 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004853
4854 proto = protocol_by_family(sk->ss_family);
4855 if (!proto || !proto->connect) {
4856 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004857 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004861
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004862 if (port1 != port2) {
4863 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4864 file, linenum, args[cur_arg], args[cur_arg + 1]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
4868
Simon Horman66183002013-02-23 10:16:43 +09004869 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004870 cur_arg += 2;
4871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004872 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004873 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 cur_arg += 2;
4875 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004876 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 newsrv->state |= SRV_BACKUP;
4878 cur_arg ++;
4879 }
Simon Hormanfa461682011-06-25 09:39:49 +09004880 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4881 newsrv->state |= SRV_NON_STICK;
4882 cur_arg ++;
4883 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004884 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4885 newsrv->state |= SRV_SEND_PROXY;
4886 cur_arg ++;
4887 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004888 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4889 newsrv->check.send_proxy = 1;
4890 cur_arg ++;
4891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004892 else if (!strcmp(args[cur_arg], "weight")) {
4893 int w;
4894 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004895 if (w < 0 || w > SRV_UWGHT_MAX) {
4896 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4897 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004901 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004902 cur_arg += 2;
4903 }
4904 else if (!strcmp(args[cur_arg], "minconn")) {
4905 newsrv->minconn = atol(args[cur_arg + 1]);
4906 cur_arg += 2;
4907 }
4908 else if (!strcmp(args[cur_arg], "maxconn")) {
4909 newsrv->maxconn = atol(args[cur_arg + 1]);
4910 cur_arg += 2;
4911 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004912 else if (!strcmp(args[cur_arg], "maxqueue")) {
4913 newsrv->maxqueue = atol(args[cur_arg + 1]);
4914 cur_arg += 2;
4915 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004916 else if (!strcmp(args[cur_arg], "slowstart")) {
4917 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004918 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004919 if (err) {
4920 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4921 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004922 err_code |= ERR_ALERT | ERR_FATAL;
4923 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004924 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004925 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004926 cur_arg += 2;
4927 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004928 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004929
4930 if (!*args[cur_arg + 1]) {
4931 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4932 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004935 }
4936
4937 newsrv->trackit = strdup(args[cur_arg + 1]);
4938
4939 cur_arg += 2;
4940 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004941 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 global.maxsock++;
4943 do_check = 1;
4944 cur_arg += 1;
4945 }
Willy Tarreau96839092010-03-29 10:02:24 +02004946 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4947 newsrv->state |= SRV_MAINTAIN;
4948 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004949 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004950 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004951 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004952 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004953 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004954 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004955 if (!strcmp(args[cur_arg + 1], "none"))
4956 newsrv->observe = HANA_OBS_NONE;
4957 else if (!strcmp(args[cur_arg + 1], "layer4"))
4958 newsrv->observe = HANA_OBS_LAYER4;
4959 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4960 if (curproxy->mode != PR_MODE_HTTP) {
4961 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4962 file, linenum, args[cur_arg + 1]);
4963 err_code |= ERR_ALERT;
4964 }
4965 newsrv->observe = HANA_OBS_LAYER7;
4966 }
4967 else {
4968 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004969 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004970 file, linenum, args[cur_arg], args[cur_arg + 1]);
4971 err_code |= ERR_ALERT | ERR_FATAL;
4972 goto out;
4973 }
4974
4975 cur_arg += 2;
4976 }
4977 else if (!strcmp(args[cur_arg], "on-error")) {
4978 if (!strcmp(args[cur_arg + 1], "fastinter"))
4979 newsrv->onerror = HANA_ONERR_FASTINTER;
4980 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4981 newsrv->onerror = HANA_ONERR_FAILCHK;
4982 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4983 newsrv->onerror = HANA_ONERR_SUDDTH;
4984 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4985 newsrv->onerror = HANA_ONERR_MARKDWN;
4986 else {
4987 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004988 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004989 file, linenum, args[cur_arg], args[cur_arg + 1]);
4990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
4992 }
4993
4994 cur_arg += 2;
4995 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004996 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4997 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4998 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4999 else {
5000 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
5001 file, linenum, args[cur_arg], args[cur_arg + 1]);
5002 err_code |= ERR_ALERT | ERR_FATAL;
5003 goto out;
5004 }
5005
5006 cur_arg += 2;
5007 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07005008 else if (!strcmp(args[cur_arg], "on-marked-up")) {
5009 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
5010 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
5011 else {
5012 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
5013 file, linenum, args[cur_arg], args[cur_arg + 1]);
5014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
5016 }
5017
5018 cur_arg += 2;
5019 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005020 else if (!strcmp(args[cur_arg], "error-limit")) {
5021 if (!*args[cur_arg + 1]) {
5022 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
5023 file, linenum, args[cur_arg]);
5024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
5026 }
5027
5028 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
5029
5030 if (newsrv->consecutive_errors_limit <= 0) {
5031 Alert("parsing [%s:%d]: %s has to be > 0.\n",
5032 file, linenum, args[cur_arg]);
5033 err_code |= ERR_ALERT | ERR_FATAL;
5034 goto out;
5035 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01005036 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005037 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005038 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005039 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005040 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005041 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01005042
Willy Tarreaubaaee002006-06-26 02:48:02 +02005043 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01005044 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
5045 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005048 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005049
Willy Tarreauef9a3602012-12-08 22:29:20 +01005050 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01005051 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005052 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005053 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005054 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005055 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005056 goto out;
5057 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005058
5059 proto = protocol_by_family(sk->ss_family);
5060 if (!proto || !proto->connect) {
5061 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5062 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
5065 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005066
Willy Tarreauef9a3602012-12-08 22:29:20 +01005067 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005068
5069 if (port_low != port_high) {
5070 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005071
5072 if (!port_low || !port_high) {
5073 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
5074 file, linenum, args[cur_arg], args[cur_arg + 1]);
5075 err_code |= ERR_ALERT | ERR_FATAL;
5076 goto out;
5077 }
5078
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005079 if (port_low <= 0 || port_low > 65535 ||
5080 port_high <= 0 || port_high > 65535 ||
5081 port_low > port_high) {
5082 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
5083 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02005084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005086 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005087 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
5088 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
5089 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005090 }
5091
Willy Tarreaubaaee002006-06-26 02:48:02 +02005092 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005093 while (*(args[cur_arg])) {
5094 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005095#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5096#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005097 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01005098 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
5099 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005102 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005103#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005104 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005105 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01005106 file, linenum, "usesrc");
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 }
5110 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005111 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5112 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005113 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005114 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5115 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005116 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5117 char *name, *end;
5118
5119 name = args[cur_arg+1] + 7;
5120 while (isspace(*name))
5121 name++;
5122
5123 end = name;
5124 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5125 end++;
5126
Willy Tarreauef9a3602012-12-08 22:29:20 +01005127 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5128 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5129 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5130 newsrv->conn_src.bind_hdr_len = end - name;
5131 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5132 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5133 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005134
5135 /* now look for an occurrence number */
5136 while (isspace(*end))
5137 end++;
5138 if (*end == ',') {
5139 end++;
5140 name = end;
5141 if (*end == '-')
5142 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005143 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005144 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005145 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005146 }
5147
Willy Tarreauef9a3602012-12-08 22:29:20 +01005148 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005149 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5150 " occurrences values smaller than %d.\n",
5151 file, linenum, MAX_HDR_HISTORY);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005155 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005156 struct sockaddr_storage *sk;
5157 int port1, port2;
5158
Willy Tarreau902636f2013-03-10 19:44:48 +01005159 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005160 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005161 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005162 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005163 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005164 goto out;
5165 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005166
5167 proto = protocol_by_family(sk->ss_family);
5168 if (!proto || !proto->connect) {
5169 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5170 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
5173 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005174
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005175 if (port1 != port2) {
5176 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5177 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
5180 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005181 newsrv->conn_src.tproxy_addr = *sk;
5182 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005183 }
5184 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005185#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005186 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005187#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005188 cur_arg += 2;
5189 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005190#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005191 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005192 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005195#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005196 } /* "usesrc" */
5197
5198 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5199#ifdef SO_BINDTODEVICE
5200 if (!*args[cur_arg + 1]) {
5201 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5202 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005205 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005206 free(newsrv->conn_src.iface_name);
5207 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5208 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005209 global.last_checks |= LSTCHK_NETADM;
5210#else
5211 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5212 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005215#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005216 cur_arg += 2;
5217 continue;
5218 }
5219 /* this keyword in not an option of "source" */
5220 break;
5221 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005222 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005223 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005224 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5225 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005230 static int srv_dumped;
5231 struct srv_kw *kw;
5232 char *err;
5233
5234 kw = srv_find_kw(args[cur_arg]);
5235 if (kw) {
5236 char *err = NULL;
5237 int code;
5238
5239 if (!kw->parse) {
5240 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5241 file, linenum, args[0], args[1], args[cur_arg]);
5242 cur_arg += 1 + kw->skip ;
5243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245 }
5246
5247 if (defsrv && !kw->default_ok) {
5248 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5249 file, linenum, args[0], args[1], args[cur_arg]);
5250 cur_arg += 1 + kw->skip ;
5251 err_code |= ERR_ALERT;
5252 continue;
5253 }
5254
5255 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5256 err_code |= code;
5257
5258 if (code) {
5259 if (err && *err) {
5260 indent_msg(&err, 2);
5261 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5262 }
5263 else
5264 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5265 file, linenum, args[0], args[1], args[cur_arg]);
5266 if (code & ERR_FATAL) {
5267 free(err);
5268 cur_arg += 1 + kw->skip;
5269 goto out;
5270 }
5271 }
5272 free(err);
5273 cur_arg += 1 + kw->skip;
5274 continue;
5275 }
5276
5277 err = NULL;
5278 if (!srv_dumped) {
5279 srv_dump_kws(&err);
5280 indent_msg(&err, 4);
5281 srv_dumped = 1;
5282 }
5283
5284 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5285 file, linenum, args[0], args[1], args[cur_arg],
5286 err ? " Registered keywords :" : "", err ? err : "");
5287 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005288
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 }
5292 }
5293
Simon Horman8c3d0be2013-11-25 10:46:40 +09005294 /* Set initial drain state using now-configured weight */
5295 set_server_drain_state(newsrv);
5296
Willy Tarreaubaaee002006-06-26 02:48:02 +02005297 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005298 int ret;
5299
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005300 if (newsrv->trackit) {
5301 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5302 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005303 err_code |= ERR_ALERT | ERR_FATAL;
5304 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005305 }
5306
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005307 /* If neither a port nor an addr was specified and no check transport
5308 * layer is forced, then the transport layer used by the checks is the
5309 * same as for the production traffic. Otherwise we use raw_sock by
5310 * default, unless one is specified.
5311 */
Simon Horman66183002013-02-23 10:16:43 +09005312 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005313#ifdef USE_OPENSSL
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005314 newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
Willy Tarreau71516332012-10-10 23:01:14 +02005315#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005316 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5317 }
Simon Horman66183002013-02-23 10:16:43 +09005318 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005319 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005320 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005321
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005322 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005323 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005324
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005325 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005326 /* not yet valid, because no port was set on
5327 * the server either. We'll check if we have
5328 * a known port on the first listener.
5329 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005330 struct listener *l;
5331
5332 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005333 newsrv->check.port = get_host_port(&l->addr);
5334 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005335 break;
5336 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005337 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005338 /*
5339 * We need at least a service port, a check port or the first tcp-check rule must
5340 * be a 'connect' one
5341 */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005342 if (!newsrv->check.port) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005343 struct tcpcheck_rule *n = NULL, *r = NULL;
5344 struct list *l;
5345
5346 r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
5347 if (!r) {
5348 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5349 file, linenum, newsrv->id);
5350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
5353 if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
5354 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",
5355 file, linenum, newsrv->id);
5356 err_code |= ERR_ALERT | ERR_FATAL;
5357 goto out;
5358 }
5359 else {
5360 /* scan the tcp-check ruleset to ensure a port has been configured */
5361 l = &newsrv->proxy->tcpcheck_rules;
5362 list_for_each_entry(n, l, list) {
5363 r = (struct tcpcheck_rule *)n->list.p;
5364 if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
5365 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",
5366 file, linenum, newsrv->id);
5367 err_code |= ERR_ALERT | ERR_FATAL;
5368 goto out;
5369 }
5370 }
5371 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005373
Willy Tarreau2f075e92013-12-03 11:11:34 +01005374 /* note: check type will be set during the config review phase */
5375 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005376 if (ret) {
5377 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005378 goto out;
5379 }
5380
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005381 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
5383
Simon Hormand60d6912013-11-25 10:46:36 +09005384 if (do_agent) {
5385 int ret;
5386
5387 if (!newsrv->agent.port) {
5388 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5389 file, linenum, newsrv->id);
5390 err_code |= ERR_ALERT | ERR_FATAL;
5391 goto out;
5392 }
5393
5394 if (!newsrv->agent.inter)
5395 newsrv->agent.inter = newsrv->check.inter;
5396
5397 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5398 if (ret) {
5399 err_code |= ret;
5400 goto out;
5401 }
5402
Willy Tarreau33434322013-12-11 21:15:19 +01005403 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005404 }
5405
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005406 if (!defsrv) {
5407 if (newsrv->state & SRV_BACKUP)
5408 curproxy->srv_bck++;
5409 else
5410 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005411
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005412 newsrv->prev_state = newsrv->state;
5413 }
William Lallemanda73203e2012-03-12 12:48:57 +01005414 }
5415
5416 else if (strcmp(args[0], "unique-id-format") == 0) {
5417 if (!*(args[1])) {
5418 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5419 err_code |= ERR_ALERT | ERR_FATAL;
5420 goto out;
5421 }
William Lallemand3203ff42012-11-11 17:30:56 +01005422 if (*(args[2])) {
5423 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5424 err_code |= ERR_ALERT | ERR_FATAL;
5425 goto out;
5426 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005427 free(curproxy->conf.uniqueid_format_string);
5428 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005429
Willy Tarreau62a61232013-04-12 18:13:46 +02005430 free(curproxy->conf.uif_file);
5431 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5432 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005433 }
William Lallemanda73203e2012-03-12 12:48:57 +01005434
5435 else if (strcmp(args[0], "unique-id-header") == 0) {
5436 if (!*(args[1])) {
5437 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
5440 }
5441 free(curproxy->header_unique_id);
5442 curproxy->header_unique_id = strdup(args[1]);
5443 }
5444
William Lallemand723b73a2012-02-08 16:37:49 +01005445 else if (strcmp(args[0], "log-format") == 0) {
5446 if (!*(args[1])) {
5447 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
William Lallemand3203ff42012-11-11 17:30:56 +01005451 if (*(args[2])) {
5452 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
5455 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005456
Willy Tarreau62a61232013-04-12 18:13:46 +02005457 if (curproxy->conf.logformat_string != default_http_log_format &&
5458 curproxy->conf.logformat_string != default_tcp_log_format &&
5459 curproxy->conf.logformat_string != clf_http_log_format)
5460 free(curproxy->conf.logformat_string);
5461 curproxy->conf.logformat_string = strdup(args[1]);
5462
5463 free(curproxy->conf.lfs_file);
5464 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5465 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005466
5467 /* get a chance to improve log-format error reporting by
5468 * reporting the correct line-number when possible.
5469 */
5470 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5471 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5472 file, linenum, curproxy->id);
5473 err_code |= ERR_WARN;
5474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 }
William Lallemand723b73a2012-02-08 16:37:49 +01005476
William Lallemand0f99e342011-10-12 17:50:54 +02005477 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5478 /* delete previous herited or defined syslog servers */
5479 struct logsrv *back;
5480
5481 if (*(args[1]) != 0) {
5482 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
5486
William Lallemand723b73a2012-02-08 16:37:49 +01005487 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5488 LIST_DEL(&tmplogsrv->list);
5489 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005490 }
5491 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005492 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005493 struct logsrv *logsrv;
5494
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005496 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005497 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005498 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005499 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005500 LIST_INIT(&node->list);
5501 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 }
5504 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005505 struct sockaddr_storage *sk;
5506 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005507
5508 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005509
William Lallemand0f99e342011-10-12 17:50:54 +02005510 logsrv->facility = get_log_facility(args[2]);
5511 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005513 err_code |= ERR_ALERT | ERR_FATAL;
5514 goto out;
5515
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516 }
5517
William Lallemand0f99e342011-10-12 17:50:54 +02005518 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005520 logsrv->level = get_log_level(args[3]);
5521 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005523 err_code |= ERR_ALERT | ERR_FATAL;
5524 goto out;
5525
Willy Tarreaubaaee002006-06-26 02:48:02 +02005526 }
5527 }
5528
William Lallemand0f99e342011-10-12 17:50:54 +02005529 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005530 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005531 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005532 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005533 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
5536
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005537 }
5538 }
5539
Willy Tarreau902636f2013-03-10 19:44:48 +01005540 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005541 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005542 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005543 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005544 goto out;
5545 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005546
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005547 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005548
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005549 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005550 if (port1 != port2) {
5551 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5552 file, linenum, args[0], args[1]);
5553 err_code |= ERR_ALERT | ERR_FATAL;
5554 goto out;
5555 }
5556
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005557 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005558 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005559 }
William Lallemand0f99e342011-10-12 17:50:54 +02005560
5561 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 }
5563 else {
5564 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5565 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 }
5569 }
5570 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005571 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005572 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005573 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005574 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005575
Willy Tarreau977b8e42006-12-29 14:19:17 +01005576 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005577 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005578
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005580 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5581 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005585
5586 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005587 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5588 free(curproxy->conn_src.iface_name);
5589 curproxy->conn_src.iface_name = NULL;
5590 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005591
Willy Tarreau902636f2013-03-10 19:44:48 +01005592 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005593 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005594 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005595 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005596 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005597 goto out;
5598 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005599
5600 proto = protocol_by_family(sk->ss_family);
5601 if (!proto || !proto->connect) {
5602 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005603 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005607
5608 if (port1 != port2) {
5609 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5610 file, linenum, args[0], args[1]);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
5614
Willy Tarreauef9a3602012-12-08 22:29:20 +01005615 curproxy->conn_src.source_addr = *sk;
5616 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005617
5618 cur_arg = 2;
5619 while (*(args[cur_arg])) {
5620 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005621#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5622#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005623 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005624 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5625 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005626 err_code |= ERR_ALERT | ERR_FATAL;
5627 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005628 }
5629#endif
5630 if (!*args[cur_arg + 1]) {
5631 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\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
5637 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005638 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5639 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005640 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005641 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5642 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005643 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5644 char *name, *end;
5645
5646 name = args[cur_arg+1] + 7;
5647 while (isspace(*name))
5648 name++;
5649
5650 end = name;
5651 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5652 end++;
5653
Willy Tarreauef9a3602012-12-08 22:29:20 +01005654 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5655 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5656 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5657 curproxy->conn_src.bind_hdr_len = end - name;
5658 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5659 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5660 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005661
5662 /* now look for an occurrence number */
5663 while (isspace(*end))
5664 end++;
5665 if (*end == ',') {
5666 end++;
5667 name = end;
5668 if (*end == '-')
5669 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005670 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005671 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005672 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005673 }
5674
Willy Tarreauef9a3602012-12-08 22:29:20 +01005675 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005676 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5677 " occurrences values smaller than %d.\n",
5678 file, linenum, MAX_HDR_HISTORY);
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
5681 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005682 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005683 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005684
Willy Tarreau902636f2013-03-10 19:44:48 +01005685 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005686 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005687 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005688 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005689 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005690 goto out;
5691 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005692
5693 proto = protocol_by_family(sk->ss_family);
5694 if (!proto || !proto->connect) {
5695 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5696 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005697 err_code |= ERR_ALERT | ERR_FATAL;
5698 goto out;
5699 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005700
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005701 if (port1 != port2) {
5702 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5703 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
5706 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005707 curproxy->conn_src.tproxy_addr = *sk;
5708 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005709 }
5710 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005711#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005712 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005713#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005714#else /* no TPROXY support */
5715 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005716 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005719#endif
5720 cur_arg += 2;
5721 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005722 }
5723
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005724 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5725#ifdef SO_BINDTODEVICE
5726 if (!*args[cur_arg + 1]) {
5727 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5728 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005731 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005732 free(curproxy->conn_src.iface_name);
5733 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5734 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005735 global.last_checks |= LSTCHK_NETADM;
5736#else
5737 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5738 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005739 err_code |= ERR_ALERT | ERR_FATAL;
5740 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005741#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005742 cur_arg += 2;
5743 continue;
5744 }
5745 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005746 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005747 err_code |= ERR_ALERT | ERR_FATAL;
5748 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005749 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005751 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5752 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5753 file, linenum, "usesrc", "source");
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 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005758 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005759 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5760 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005764
5765 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005766 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005767 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005768 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 }
5771 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005773 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005774 args[0], args[1], NULL, (const char **)args+2);
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], "reqdeny")) { /* deny a request if a header matches this 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_DENY, 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], "reqpass")) { /* pass this header without allowing or denying the request */
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_PASS, 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], "reqallow")) { /* allow a request if a header matches this regex */
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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005799 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005805 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005806 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
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_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005809 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005810 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005811 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005812 }
5813 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring 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, REG_ICASE,
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 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005821 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5823 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005824 err_code |= ERR_ALERT | ERR_FATAL;
5825 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005826 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005827
5828 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005829 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005830 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005831 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 }
5834 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005836 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005837 args[0], args[1], NULL, (const char **)args+2);
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], "reqideny")) { /* deny a request if a header matches this 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_DENY, 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], "reqipass")) { /* pass this header without allowing or denying the request */
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_PASS, 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], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
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_ALLOW, 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 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005862 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit 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_TARPIT, 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 Tarreaub8750a82006-09-03 09:56:00 +02005868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005869 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005870 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005871
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 if (curproxy == &defproxy) {
5873 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005874 err_code |= ERR_ALERT | ERR_FATAL;
5875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005877 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005878 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879
Willy Tarreaubaaee002006-06-26 02:48:02 +02005880 if (*(args[1]) == 0) {
5881 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005885
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005886 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005887 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5888 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5889 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005890 err_code |= ERR_ALERT | ERR_FATAL;
5891 goto out;
5892 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005893 err_code |= warnif_cond_conflicts(cond,
5894 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5895 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005896 }
5897 else if (*args[2]) {
5898 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5899 file, linenum, args[0], args[2]);
5900 err_code |= ERR_ALERT | ERR_FATAL;
5901 goto out;
5902 }
5903
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005904 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005905 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005906 wl->s = strdup(args[1]);
5907 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005908 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005909 }
5910 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005911 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5913 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005914 err_code |= ERR_ALERT | ERR_FATAL;
5915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005917
Willy Tarreauade5ec42010-01-28 19:33:49 +01005918 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005919 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005920 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005921 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 }
5924 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
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_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005927 args[0], args[1], NULL, (const char **)args+2);
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], "rspdeny")) { /* block 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_DENY, 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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005939 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5941 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005942 err_code |= ERR_ALERT | ERR_FATAL;
5943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 }
5945
Willy Tarreauade5ec42010-01-28 19:33:49 +01005946 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005947 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005948 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005949 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951 }
5952 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
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_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005955 args[0], args[1], NULL, (const char **)args+2);
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], "rspideny")) { /* block 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_DENY, 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], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005967 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005968
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 if (curproxy == &defproxy) {
5970 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005974 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005975 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 if (*(args[1]) == 0) {
5978 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 }
5982
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005983 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005984 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5985 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5986 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005987 err_code |= ERR_ALERT | ERR_FATAL;
5988 goto out;
5989 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005990 err_code |= warnif_cond_conflicts(cond,
5991 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5992 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005993 }
5994 else if (*args[2]) {
5995 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5996 file, linenum, args[0], args[2]);
5997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
5999 }
6000
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006001 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006002 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006003 wl->s = strdup(args[1]);
6004 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 }
6006 else if (!strcmp(args[0], "errorloc") ||
6007 !strcmp(args[0], "errorloc302") ||
6008 !strcmp(args[0], "errorloc303")) { /* error location */
6009 int errnum, errlen;
6010 char *err;
6011
Willy Tarreau977b8e42006-12-29 14:19:17 +01006012 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006013 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006014
Willy Tarreaubaaee002006-06-26 02:48:02 +02006015 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006016 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 }
6020
6021 errnum = atol(args[1]);
6022 if (!strcmp(args[0], "errorloc303")) {
6023 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
6024 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
6025 } else {
6026 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
6027 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
6028 }
6029
Willy Tarreau0f772532006-12-23 20:51:41 +01006030 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6031 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006032 chunk_destroy(&curproxy->errmsg[rc]);
6033 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006034 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006036 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006037
6038 if (rc >= HTTP_ERR_SIZE) {
6039 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6040 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006041 free(err);
6042 }
6043 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006044 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6045 int errnum, errlen, fd;
6046 char *err;
6047 struct stat stat;
6048
6049 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006050 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006051
6052 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006053 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006054 err_code |= ERR_ALERT | ERR_FATAL;
6055 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006056 }
6057
6058 fd = open(args[2], O_RDONLY);
6059 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6060 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6061 file, linenum, args[2], args[1]);
6062 if (fd >= 0)
6063 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006064 err_code |= ERR_ALERT | ERR_FATAL;
6065 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006066 }
6067
Willy Tarreau27a674e2009-08-17 07:23:33 +02006068 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006069 errlen = stat.st_size;
6070 } else {
6071 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006072 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006073 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006074 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006075 }
6076
6077 err = malloc(errlen); /* malloc() must succeed during parsing */
6078 errnum = read(fd, err, errlen);
6079 if (errnum != errlen) {
6080 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6081 file, linenum, args[2], args[1]);
6082 close(fd);
6083 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006084 err_code |= ERR_ALERT | ERR_FATAL;
6085 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006086 }
6087 close(fd);
6088
6089 errnum = atol(args[1]);
6090 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6091 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006092 chunk_destroy(&curproxy->errmsg[rc]);
6093 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006094 break;
6095 }
6096 }
6097
6098 if (rc >= HTTP_ERR_SIZE) {
6099 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6100 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006101 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006102 free(err);
6103 }
6104 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006105 else if (!strcmp(args[0], "compression")) {
6106 struct comp *comp;
6107 if (curproxy->comp == NULL) {
6108 comp = calloc(1, sizeof(struct comp));
6109 curproxy->comp = comp;
6110 } else {
6111 comp = curproxy->comp;
6112 }
6113
6114 if (!strcmp(args[1], "algo")) {
6115 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006116 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006117
William Lallemand82fe75c2012-10-23 10:25:10 +02006118 cur_arg = 2;
6119 if (!*args[cur_arg]) {
6120 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6121 file, linenum, args[0]);
6122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
6124 }
6125 while (*(args[cur_arg])) {
6126 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6127 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6128 file, linenum, args[0], args[cur_arg]);
6129 err_code |= ERR_ALERT | ERR_FATAL;
6130 goto out;
6131 }
William Lallemand552df672012-11-07 13:21:47 +01006132 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6133 curproxy->comp->algos->end(&ctx);
6134 } else {
6135 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6136 file, linenum, args[0], args[cur_arg]);
6137 err_code |= ERR_ALERT | ERR_FATAL;
6138 goto out;
6139 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006140 cur_arg ++;
6141 continue;
6142 }
6143 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006144 else if (!strcmp(args[1], "offload")) {
6145 comp->offload = 1;
6146 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006147 else if (!strcmp(args[1], "type")) {
6148 int cur_arg;
6149 cur_arg = 2;
6150 if (!*args[cur_arg]) {
6151 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6152 file, linenum, args[0]);
6153 err_code |= ERR_ALERT | ERR_FATAL;
6154 goto out;
6155 }
6156 while (*(args[cur_arg])) {
6157 comp_append_type(comp, args[cur_arg]);
6158 cur_arg ++;
6159 continue;
6160 }
6161 }
6162 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006163 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006164 file, linenum, args[0]);
6165 err_code |= ERR_ALERT | ERR_FATAL;
6166 goto out;
6167 }
6168 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006170 struct cfg_kw_list *kwl;
6171 int index;
6172
6173 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6174 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6175 if (kwl->kw[index].section != CFG_LISTEN)
6176 continue;
6177 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6178 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006179 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006180 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006181 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006182 err_code |= ERR_ALERT | ERR_FATAL;
6183 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006184 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006185 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006186 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006187 err_code |= ERR_WARN;
6188 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006189 }
Willy Tarreau93893792009-07-23 13:19:11 +02006190 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006191 }
6192 }
6193 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006194
Willy Tarreau6daf3432008-01-22 16:44:08 +01006195 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006196 err_code |= ERR_ALERT | ERR_FATAL;
6197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 }
Willy Tarreau93893792009-07-23 13:19:11 +02006199 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006200 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006201 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202}
6203
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006204int
6205cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6206{
6207
6208 int err_code = 0;
6209 const char *err;
6210
6211 if (!strcmp(args[0], "userlist")) { /* new userlist */
6212 struct userlist *newul;
6213
6214 if (!*args[1]) {
6215 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6216 file, linenum, args[0]);
6217 err_code |= ERR_ALERT | ERR_FATAL;
6218 goto out;
6219 }
6220
6221 err = invalid_char(args[1]);
6222 if (err) {
6223 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6224 file, linenum, *err, args[0], args[1]);
6225 err_code |= ERR_ALERT | ERR_FATAL;
6226 goto out;
6227 }
6228
6229 for (newul = userlist; newul; newul = newul->next)
6230 if (!strcmp(newul->name, args[1])) {
6231 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6232 file, linenum, args[1]);
6233 err_code |= ERR_WARN;
6234 goto out;
6235 }
6236
6237 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6238 if (!newul) {
6239 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6240 err_code |= ERR_ALERT | ERR_ABORT;
6241 goto out;
6242 }
6243
6244 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6245 newul->name = strdup(args[1]);
6246
6247 if (!newul->groupusers | !newul->name) {
6248 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6249 err_code |= ERR_ALERT | ERR_ABORT;
6250 goto out;
6251 }
6252
6253 newul->next = userlist;
6254 userlist = newul;
6255
6256 } else if (!strcmp(args[0], "group")) { /* new group */
6257 int cur_arg, i;
6258 const char *err;
6259
6260 if (!*args[1]) {
6261 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6262 file, linenum, args[0]);
6263 err_code |= ERR_ALERT | ERR_FATAL;
6264 goto out;
6265 }
6266
6267 err = invalid_char(args[1]);
6268 if (err) {
6269 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6270 file, linenum, *err, args[0], args[1]);
6271 err_code |= ERR_ALERT | ERR_FATAL;
6272 goto out;
6273 }
6274
6275 for(i = 0; i < userlist->grpcnt; i++)
6276 if (!strcmp(userlist->groups[i], args[1])) {
6277 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6278 file, linenum, args[1], userlist->name);
6279 err_code |= ERR_ALERT;
6280 goto out;
6281 }
6282
6283 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6284 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6285 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6286 err_code |= ERR_ALERT | ERR_FATAL;
6287 goto out;
6288 }
6289
6290 cur_arg = 2;
6291
6292 while (*args[cur_arg]) {
6293 if (!strcmp(args[cur_arg], "users")) {
6294 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6295 cur_arg += 2;
6296 continue;
6297 } else {
6298 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6299 file, linenum, args[0]);
6300 err_code |= ERR_ALERT | ERR_FATAL;
6301 goto out;
6302 }
6303 }
6304
6305 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6306 } else if (!strcmp(args[0], "user")) { /* new user */
6307 struct auth_users *newuser;
6308 int cur_arg;
6309
6310 if (!*args[1]) {
6311 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6312 file, linenum, args[0]);
6313 err_code |= ERR_ALERT | ERR_FATAL;
6314 goto out;
6315 }
6316
6317 for (newuser = userlist->users; newuser; newuser = newuser->next)
6318 if (!strcmp(newuser->user, args[1])) {
6319 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6320 file, linenum, args[1], userlist->name);
6321 err_code |= ERR_ALERT;
6322 goto out;
6323 }
6324
6325 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6326 if (!newuser) {
6327 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6328 err_code |= ERR_ALERT | ERR_ABORT;
6329 goto out;
6330 }
6331
6332 newuser->user = strdup(args[1]);
6333
6334 newuser->next = userlist->users;
6335 userlist->users = newuser;
6336
6337 cur_arg = 2;
6338
6339 while (*args[cur_arg]) {
6340 if (!strcmp(args[cur_arg], "password")) {
6341#ifndef CONFIG_HAP_CRYPT
6342 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6343 file, linenum);
6344 err_code |= ERR_ALERT;
6345#endif
6346 newuser->pass = strdup(args[cur_arg + 1]);
6347 cur_arg += 2;
6348 continue;
6349 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6350 newuser->pass = strdup(args[cur_arg + 1]);
6351 newuser->flags |= AU_O_INSECURE;
6352 cur_arg += 2;
6353 continue;
6354 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006355 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006356 cur_arg += 2;
6357 continue;
6358 } else {
6359 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6360 file, linenum, args[0]);
6361 err_code |= ERR_ALERT | ERR_FATAL;
6362 goto out;
6363 }
6364 }
6365 } else {
6366 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6367 err_code |= ERR_ALERT | ERR_FATAL;
6368 }
6369
6370out:
6371 return err_code;
6372}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373
6374/*
6375 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006376 * Returns the error code, 0 if OK, or any combination of :
6377 * - ERR_ABORT: must abort ASAP
6378 * - ERR_FATAL: we can continue parsing but not start the service
6379 * - ERR_WARN: a warning has been emitted
6380 * - ERR_ALERT: an alert has been emitted
6381 * Only the two first ones can stop processing, the two others are just
6382 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006384int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006385{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006386 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006387 FILE *f;
6388 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006389 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006390 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 if ((f=fopen(file,"r")) == NULL)
6393 return -1;
6394
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006395 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006396 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006397 char *end;
6398 char *args[MAX_LINE_ARGS + 1];
6399 char *line = thisline;
6400
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 linenum++;
6402
6403 end = line + strlen(line);
6404
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006405 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6406 /* Check if we reached the limit and the last char is not \n.
6407 * Watch out for the last line without the terminating '\n'!
6408 */
6409 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006410 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006411 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006412 }
6413
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006415 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 line++;
6417
6418 arg = 0;
6419 args[arg] = line;
6420
6421 while (*line && arg < MAX_LINE_ARGS) {
6422 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6423 * C equivalent value. Other combinations left unchanged (eg: \1).
6424 */
6425 if (*line == '\\') {
6426 int skip = 0;
6427 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6428 *line = line[1];
6429 skip = 1;
6430 }
6431 else if (line[1] == 'r') {
6432 *line = '\r';
6433 skip = 1;
6434 }
6435 else if (line[1] == 'n') {
6436 *line = '\n';
6437 skip = 1;
6438 }
6439 else if (line[1] == 't') {
6440 *line = '\t';
6441 skip = 1;
6442 }
6443 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006444 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445 unsigned char hex1, hex2;
6446 hex1 = toupper(line[2]) - '0';
6447 hex2 = toupper(line[3]) - '0';
6448 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6449 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6450 *line = (hex1<<4) + hex2;
6451 skip = 3;
6452 }
6453 else {
6454 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006455 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006456 }
6457 }
6458 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006459 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006460 end -= skip;
6461 }
6462 line++;
6463 }
6464 else if (*line == '#' || *line == '\n' || *line == '\r') {
6465 /* end of string, end of loop */
6466 *line = 0;
6467 break;
6468 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006469 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006470 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006471 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006472 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 line++;
6474 args[++arg] = line;
6475 }
6476 else {
6477 line++;
6478 }
6479 }
6480
6481 /* empty line */
6482 if (!**args)
6483 continue;
6484
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006485 if (*line) {
6486 /* we had to stop due to too many args.
6487 * Let's terminate the string, print the offending part then cut the
6488 * last arg.
6489 */
6490 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6491 line++;
6492 *line = '\0';
6493
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006494 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006495 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006496 err_code |= ERR_ALERT | ERR_FATAL;
6497 args[arg] = line;
6498 }
6499
Willy Tarreau540abe42007-05-02 20:50:16 +02006500 /* zero out remaining args and ensure that at least one entry
6501 * is zeroed out.
6502 */
6503 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 args[arg] = line;
6505 }
6506
Willy Tarreau3842f002009-06-14 11:39:52 +02006507 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006508 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006509 char *tmp;
6510
Willy Tarreau3842f002009-06-14 11:39:52 +02006511 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006512 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006513 for (arg=0; *args[arg+1]; arg++)
6514 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006515 *tmp = '\0'; // fix the next arg to \0
6516 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006517 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006518 else if (!strcmp(args[0], "default")) {
6519 kwm = KWM_DEF;
6520 for (arg=0; *args[arg+1]; arg++)
6521 args[arg] = args[arg+1]; // shift args after inversion
6522 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006523
William Lallemand0f99e342011-10-12 17:50:54 +02006524 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6525 strcmp(args[0], "log") != 0) {
6526 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006527 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006528 }
6529
Willy Tarreau977b8e42006-12-29 14:19:17 +01006530 if (!strcmp(args[0], "listen") ||
6531 !strcmp(args[0], "frontend") ||
6532 !strcmp(args[0], "backend") ||
6533 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006534 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006535 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006536 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006537 cursection = strdup(args[0]);
6538 }
6539 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006541 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006542 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006543 }
6544 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006545 confsect = CFG_USERLIST;
6546 free(cursection);
6547 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006548 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006549 else if (!strcmp(args[0], "peers")) {
6550 confsect = CFG_PEERS;
6551 free(cursection);
6552 cursection = strdup(args[0]);
6553 }
6554
Willy Tarreaubaaee002006-06-26 02:48:02 +02006555 /* else it's a section keyword */
6556
6557 switch (confsect) {
6558 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006559 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006560 break;
6561 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006562 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006563 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006564 case CFG_USERLIST:
6565 err_code |= cfg_parse_users(file, linenum, args, kwm);
6566 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006567 case CFG_PEERS:
6568 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6569 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006571 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006572 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006573 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006574
6575 if (err_code & ERR_ABORT)
6576 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006578 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006579 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006581 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006582}
6583
Willy Tarreaubb925012009-07-23 13:36:36 +02006584/*
6585 * Returns the error code, 0 if OK, or any combination of :
6586 * - ERR_ABORT: must abort ASAP
6587 * - ERR_FATAL: we can continue parsing but not start the service
6588 * - ERR_WARN: a warning has been emitted
6589 * - ERR_ALERT: an alert has been emitted
6590 * Only the two first ones can stop processing, the two others are just
6591 * indicators.
6592 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006593int check_config_validity()
6594{
6595 int cfgerr = 0;
6596 struct proxy *curproxy = NULL;
6597 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006598 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006599 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006600 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006601 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006603 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604 /*
6605 * Now, check for the integrity of all that we have collected.
6606 */
6607
6608 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006609 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006610
Willy Tarreau193b8c62012-11-22 00:17:38 +01006611 if (!global.tune.max_http_hdr)
6612 global.tune.max_http_hdr = MAX_HTTP_HDR;
6613
6614 if (!global.tune.cookie_len)
6615 global.tune.cookie_len = CAPTURE_LEN;
6616
6617 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6618
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006619 /* first, we will invert the proxy list order */
6620 curproxy = NULL;
6621 while (proxy) {
6622 struct proxy *next;
6623
6624 next = proxy->next;
6625 proxy->next = curproxy;
6626 curproxy = proxy;
6627 if (!next)
6628 break;
6629 proxy = next;
6630 }
6631
Willy Tarreaubaaee002006-06-26 02:48:02 +02006632 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006633 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006634 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006635 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006636 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006637 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006638 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006639 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006640
Willy Tarreau050536d2012-10-04 08:47:34 +02006641 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006642 /* proxy ID not set, use automatic numbering with first
6643 * spare entry starting with next_pxid.
6644 */
6645 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6646 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6647 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006648 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006649 next_pxid++;
6650
Willy Tarreau55ea7572007-06-17 19:56:27 +02006651
Willy Tarreaubaaee002006-06-26 02:48:02 +02006652 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006653 /* ensure we don't keep listeners uselessly bound */
6654 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006655 curproxy = curproxy->next;
6656 continue;
6657 }
6658
Willy Tarreau16a21472012-11-19 12:39:59 +01006659 /* number of processes this proxy is bound to */
6660 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6661
Willy Tarreauff01a212009-03-15 13:46:16 +01006662 switch (curproxy->mode) {
6663 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006664 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006665 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006666 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6667 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006668 cfgerr++;
6669 }
6670
6671 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006672 Warning("config : servers will be ignored for %s '%s'.\n",
6673 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006674 break;
6675
6676 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006677 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006678 break;
6679
6680 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006681 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006682 break;
6683 }
6684
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006685 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006686 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006687 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006688 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6689 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006690 cfgerr++;
6691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006692#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006693 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006694 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6695 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006696 cfgerr++;
6697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006698#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006699 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006700 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6701 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006702 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006703 }
6704 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006705 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006706 /* If no LB algo is set in a backend, and we're not in
6707 * transparent mode, dispatch mode nor proxy mode, we
6708 * want to use balance roundrobin by default.
6709 */
6710 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6711 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006712 }
6713 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006714
Willy Tarreau1620ec32011-08-06 17:05:02 +02006715 if (curproxy->options & PR_O_DISPATCH)
6716 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6717 else if (curproxy->options & PR_O_HTTP_PROXY)
6718 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6719 else if (curproxy->options & PR_O_TRANSP)
6720 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006721
Willy Tarreau1620ec32011-08-06 17:05:02 +02006722 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6723 if (curproxy->options & PR_O_DISABLE404) {
6724 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6725 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6726 err_code |= ERR_WARN;
6727 curproxy->options &= ~PR_O_DISABLE404;
6728 }
6729 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6730 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6731 "send-state", proxy_type_str(curproxy), curproxy->id);
6732 err_code |= ERR_WARN;
6733 curproxy->options &= ~PR_O2_CHK_SNDST;
6734 }
Willy Tarreauef781042010-01-27 11:53:01 +01006735 }
6736
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006737 /* if a default backend was specified, let's find it */
6738 if (curproxy->defbe.name) {
6739 struct proxy *target;
6740
Alex Williams96532db2009-11-01 21:27:13 -05006741 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006742 if (!target) {
6743 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6744 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006745 cfgerr++;
6746 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006747 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6748 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006749 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006750 } else {
6751 free(curproxy->defbe.name);
6752 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006753 /* we force the backend to be present on at least all of
6754 * the frontend's processes.
6755 */
6756 target->bind_proc = curproxy->bind_proc ?
6757 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006758
6759 /* Emit a warning if this proxy also has some servers */
6760 if (curproxy->srv) {
6761 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6762 curproxy->id);
6763 err_code |= ERR_WARN;
6764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006765 }
6766 }
6767
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006768 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006769 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6770 /* map jump target for ACT_SETBE in req_rep chain */
6771 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006772 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006773 struct proxy *target;
6774
Willy Tarreaua496b602006-12-17 23:15:24 +01006775 if (exp->action != ACT_SETBE)
6776 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006777
Alex Williams96532db2009-11-01 21:27:13 -05006778 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006779 if (!target) {
6780 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6781 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006782 cfgerr++;
6783 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006784 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6785 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006786 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006787 } else {
6788 free((void *)exp->replace);
6789 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006790 /* we force the backend to be present on at least all of
6791 * the frontend's processes.
6792 */
6793 target->bind_proc = curproxy->bind_proc ?
6794 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006795 }
6796 }
6797 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006798
6799 /* find the target proxy for 'use_backend' rules */
6800 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006801 struct proxy *target;
6802
Alex Williams96532db2009-11-01 21:27:13 -05006803 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006804
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006805 if (!target) {
6806 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6807 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006808 cfgerr++;
6809 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006810 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6811 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006812 cfgerr++;
6813 } else {
6814 free((void *)rule->be.name);
6815 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006816 /* we force the backend to be present on at least all of
6817 * the frontend's processes.
6818 */
6819 target->bind_proc = curproxy->bind_proc ?
6820 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006821 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006822 }
6823
6824 /* find the target proxy for 'use_backend' rules */
6825 list_for_each_entry(srule, &curproxy->server_rules, list) {
6826 struct server *target = findserver(curproxy, srule->srv.name);
6827
6828 if (!target) {
6829 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6830 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6831 cfgerr++;
6832 continue;
6833 }
6834 free((void *)srule->srv.name);
6835 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006836 }
6837
Emeric Brunb982a3d2010-01-04 15:45:53 +01006838 /* find the target table for 'stick' rules */
6839 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6840 struct proxy *target;
6841
Emeric Brun1d33b292010-01-04 15:47:17 +01006842 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6843 if (mrule->flags & STK_IS_STORE)
6844 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6845
Emeric Brunb982a3d2010-01-04 15:45:53 +01006846 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006847 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006848 else
6849 target = curproxy;
6850
6851 if (!target) {
6852 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6853 curproxy->id, mrule->table.name);
6854 cfgerr++;
6855 }
6856 else if (target->table.size == 0) {
6857 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6858 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6859 cfgerr++;
6860 }
Willy Tarreau12785782012-04-27 21:37:17 +02006861 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6862 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006863 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6864 cfgerr++;
6865 }
6866 else {
6867 free((void *)mrule->table.name);
6868 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006869 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006870 }
6871 }
6872
6873 /* find the target table for 'store response' rules */
6874 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6875 struct proxy *target;
6876
Emeric Brun1d33b292010-01-04 15:47:17 +01006877 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6878
Emeric Brunb982a3d2010-01-04 15:45:53 +01006879 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006880 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006881 else
6882 target = curproxy;
6883
6884 if (!target) {
6885 Alert("Proxy '%s': unable to find store table '%s'.\n",
6886 curproxy->id, mrule->table.name);
6887 cfgerr++;
6888 }
6889 else if (target->table.size == 0) {
6890 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6891 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6892 cfgerr++;
6893 }
Willy Tarreau12785782012-04-27 21:37:17 +02006894 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6895 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006896 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6897 cfgerr++;
6898 }
6899 else {
6900 free((void *)mrule->table.name);
6901 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006902 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006903 }
6904 }
6905
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006906 /* find the target table for 'tcp-request' layer 4 rules */
6907 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6908 struct proxy *target;
6909
Willy Tarreaub4c84932013-07-23 19:15:30 +02006910 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006911 continue;
6912
6913 if (trule->act_prm.trk_ctr.table.n)
6914 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6915 else
6916 target = curproxy;
6917
6918 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006919 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6920 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006921 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006922 cfgerr++;
6923 }
6924 else if (target->table.size == 0) {
6925 Alert("Proxy '%s': table '%s' used but not configured.\n",
6926 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6927 cfgerr++;
6928 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006929 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6930 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6931 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 +01006932 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006933 cfgerr++;
6934 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006935 else {
6936 free(trule->act_prm.trk_ctr.table.n);
6937 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006938 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006939 * to pass a list of counters to track and allocate them right here using
6940 * stktable_alloc_data_type().
6941 */
6942 }
6943 }
6944
Willy Tarreaud1f96522010-08-03 19:34:32 +02006945 /* find the target table for 'tcp-request' layer 6 rules */
6946 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6947 struct proxy *target;
6948
Willy Tarreaub4c84932013-07-23 19:15:30 +02006949 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006950 continue;
6951
6952 if (trule->act_prm.trk_ctr.table.n)
6953 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6954 else
6955 target = curproxy;
6956
6957 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006958 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6959 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006960 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006961 cfgerr++;
6962 }
6963 else if (target->table.size == 0) {
6964 Alert("Proxy '%s': table '%s' used but not configured.\n",
6965 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6966 cfgerr++;
6967 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006968 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6969 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6970 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 +01006971 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006972 cfgerr++;
6973 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006974 else {
6975 free(trule->act_prm.trk_ctr.table.n);
6976 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006977 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006978 * to pass a list of counters to track and allocate them right here using
6979 * stktable_alloc_data_type().
6980 */
6981 }
6982 }
6983
Emeric Brun32da3c42010-09-23 18:39:19 +02006984 if (curproxy->table.peers.name) {
6985 struct peers *curpeers = peers;
6986
6987 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6988 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6989 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006990 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006991 break;
6992 }
6993 }
6994
6995 if (!curpeers) {
6996 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6997 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006998 free((void *)curproxy->table.peers.name);
6999 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007000 cfgerr++;
7001 }
7002 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007003 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7004 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007005 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007006 cfgerr++;
7007 }
7008 }
7009
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007010 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007011 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007012 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7013 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7014 "proxy", curproxy->id);
7015 cfgerr++;
7016 goto out_uri_auth_compat;
7017 }
7018
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007019 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007020 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007021 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007022 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007023
Willy Tarreau95fa4692010-02-01 13:05:50 +01007024 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7025 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007026
7027 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007028 uri_auth_compat_req[i++] = "realm";
7029 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7030 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007031
Willy Tarreau95fa4692010-02-01 13:05:50 +01007032 uri_auth_compat_req[i++] = "unless";
7033 uri_auth_compat_req[i++] = "{";
7034 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7035 uri_auth_compat_req[i++] = "}";
7036 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007037
Willy Tarreauff011f22011-01-06 17:51:27 +01007038 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7039 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007040 cfgerr++;
7041 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007042 }
7043
Willy Tarreauff011f22011-01-06 17:51:27 +01007044 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007045
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007046 if (curproxy->uri_auth->auth_realm) {
7047 free(curproxy->uri_auth->auth_realm);
7048 curproxy->uri_auth->auth_realm = NULL;
7049 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007050
7051 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007052 }
7053out_uri_auth_compat:
7054
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007055 /* compile the log format */
7056 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007057 if (curproxy->conf.logformat_string != default_http_log_format &&
7058 curproxy->conf.logformat_string != default_tcp_log_format &&
7059 curproxy->conf.logformat_string != clf_http_log_format)
7060 free(curproxy->conf.logformat_string);
7061 curproxy->conf.logformat_string = NULL;
7062 free(curproxy->conf.lfs_file);
7063 curproxy->conf.lfs_file = NULL;
7064 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007065 }
7066
Willy Tarreau62a61232013-04-12 18:13:46 +02007067 if (curproxy->conf.logformat_string) {
7068 curproxy->conf.args.ctx = ARGC_LOG;
7069 curproxy->conf.args.file = curproxy->conf.lfs_file;
7070 curproxy->conf.args.line = curproxy->conf.lfs_line;
7071 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007072 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02007073 curproxy->conf.args.file = NULL;
7074 curproxy->conf.args.line = 0;
7075 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007076
Willy Tarreau62a61232013-04-12 18:13:46 +02007077 if (curproxy->conf.uniqueid_format_string) {
7078 curproxy->conf.args.ctx = ARGC_UIF;
7079 curproxy->conf.args.file = curproxy->conf.uif_file;
7080 curproxy->conf.args.line = curproxy->conf.uif_line;
7081 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007082 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02007083 curproxy->conf.args.file = NULL;
7084 curproxy->conf.args.line = 0;
7085 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007086
7087 /* only now we can check if some args remain unresolved */
7088 cfgerr += smp_resolve_args(curproxy);
7089 if (!cfgerr)
7090 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007091
Willy Tarreau2738a142006-07-08 17:28:09 +02007092 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007093 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007094 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007095 (!curproxy->timeout.connect ||
7096 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007097 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007098 " | While not properly invalid, you will certainly encounter various problems\n"
7099 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007100 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007101 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007102 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007103 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007104
Willy Tarreau1fa31262007-12-03 00:36:16 +01007105 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7106 * We must still support older configurations, so let's find out whether those
7107 * parameters have been set or must be copied from contimeouts.
7108 */
7109 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007110 if (!curproxy->timeout.tarpit ||
7111 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007112 /* tarpit timeout not set. We search in the following order:
7113 * default.tarpit, curr.connect, default.connect.
7114 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007115 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007116 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007117 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007118 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007119 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007120 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007121 }
7122 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007123 (!curproxy->timeout.queue ||
7124 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007125 /* queue timeout not set. We search in the following order:
7126 * default.queue, curr.connect, default.connect.
7127 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007128 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007129 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007130 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007131 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007132 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007133 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007134 }
7135 }
7136
Willy Tarreau1620ec32011-08-06 17:05:02 +02007137 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007138 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7139 curproxy->check_req = (char *)malloc(curproxy->check_len);
7140 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007141 }
7142
Willy Tarreau193b8c62012-11-22 00:17:38 +01007143 /* ensure that cookie capture length is not too large */
7144 if (curproxy->capture_len >= global.tune.cookie_len) {
7145 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7146 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7147 err_code |= ERR_WARN;
7148 curproxy->capture_len = global.tune.cookie_len - 1;
7149 }
7150
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007151 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007152 if (curproxy->nb_req_cap) {
7153 if (curproxy->mode == PR_MODE_HTTP) {
7154 curproxy->req_cap_pool = create_pool("ptrcap",
7155 curproxy->nb_req_cap * sizeof(char *),
7156 MEM_F_SHARED);
7157 } else {
7158 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7159 proxy_type_str(curproxy), curproxy->id);
7160 err_code |= ERR_WARN;
7161 curproxy->to_log &= ~LW_REQHDR;
7162 curproxy->nb_req_cap = 0;
7163 }
7164 }
7165
7166 if (curproxy->nb_rsp_cap) {
7167 if (curproxy->mode == PR_MODE_HTTP) {
7168 curproxy->rsp_cap_pool = create_pool("ptrcap",
7169 curproxy->nb_rsp_cap * sizeof(char *),
7170 MEM_F_SHARED);
7171 } else {
7172 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7173 proxy_type_str(curproxy), curproxy->id);
7174 err_code |= ERR_WARN;
7175 curproxy->to_log &= ~LW_REQHDR;
7176 curproxy->nb_rsp_cap = 0;
7177 }
7178 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007179
Willy Tarreaubaaee002006-06-26 02:48:02 +02007180 /* first, we will invert the servers list order */
7181 newsrv = NULL;
7182 while (curproxy->srv) {
7183 struct server *next;
7184
7185 next = curproxy->srv->next;
7186 curproxy->srv->next = newsrv;
7187 newsrv = curproxy->srv;
7188 if (!next)
7189 break;
7190 curproxy->srv = next;
7191 }
7192
Willy Tarreau17edc812014-01-03 12:14:34 +01007193 /* Check that no server name conflicts. This causes trouble in the stats.
7194 * We only emit a warning for the first conflict affecting each server,
7195 * in order to avoid combinatory explosion if all servers have the same
7196 * name. We do that only for servers which do not have an explicit ID,
7197 * because these IDs were made also for distinguishing them and we don't
7198 * want to annoy people who correctly manage them.
7199 */
7200 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7201 struct server *other_srv;
7202
7203 if (newsrv->puid)
7204 continue;
7205
7206 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7207 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7208 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7209 newsrv->conf.file, newsrv->conf.line,
7210 proxy_type_str(curproxy), curproxy->id,
7211 newsrv->id, other_srv->conf.line);
7212 break;
7213 }
7214 }
7215 }
7216
Willy Tarreaudd701652010-05-25 23:03:02 +02007217 /* assign automatic UIDs to servers which don't have one yet */
7218 next_id = 1;
7219 newsrv = curproxy->srv;
7220 while (newsrv != NULL) {
7221 if (!newsrv->puid) {
7222 /* server ID not set, use automatic numbering with first
7223 * spare entry starting with next_svid.
7224 */
7225 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7226 newsrv->conf.id.key = newsrv->puid = next_id;
7227 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7228 }
7229 next_id++;
7230 newsrv = newsrv->next;
7231 }
7232
Willy Tarreau20697042007-11-15 23:26:18 +01007233 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007234 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007235
Willy Tarreau62c3be22012-01-20 13:12:32 +01007236 /*
7237 * If this server supports a maxconn parameter, it needs a dedicated
7238 * tasks to fill the emptied slots when a connection leaves.
7239 * Also, resolve deferred tracking dependency if needed.
7240 */
7241 newsrv = curproxy->srv;
7242 while (newsrv != NULL) {
7243 if (newsrv->minconn > newsrv->maxconn) {
7244 /* Only 'minconn' was specified, or it was higher than or equal
7245 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7246 * this will avoid further useless expensive computations.
7247 */
7248 newsrv->maxconn = newsrv->minconn;
7249 } else if (newsrv->maxconn && !newsrv->minconn) {
7250 /* minconn was not specified, so we set it to maxconn */
7251 newsrv->minconn = newsrv->maxconn;
7252 }
7253
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007254#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007255 if (newsrv->use_ssl || newsrv->check.use_ssl)
7256 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007257#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007258
Willy Tarreau2f075e92013-12-03 11:11:34 +01007259 /* set the check type on the server */
7260 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7261
Willy Tarreau62c3be22012-01-20 13:12:32 +01007262 if (newsrv->trackit) {
7263 struct proxy *px;
7264 struct server *srv;
7265 char *pname, *sname;
7266
7267 pname = newsrv->trackit;
7268 sname = strrchr(pname, '/');
7269
7270 if (sname)
7271 *sname++ = '\0';
7272 else {
7273 sname = pname;
7274 pname = NULL;
7275 }
7276
7277 if (pname) {
7278 px = findproxy(pname, PR_CAP_BE);
7279 if (!px) {
7280 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7281 proxy_type_str(curproxy), curproxy->id,
7282 newsrv->id, pname);
7283 cfgerr++;
7284 goto next_srv;
7285 }
7286 } else
7287 px = curproxy;
7288
7289 srv = findserver(px, sname);
7290 if (!srv) {
7291 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7292 proxy_type_str(curproxy), curproxy->id,
7293 newsrv->id, sname);
7294 cfgerr++;
7295 goto next_srv;
7296 }
7297
Willy Tarreauff5ae352013-12-11 20:36:34 +01007298 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007299 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7300 "tracking as it does not have checks enabled.\n",
7301 proxy_type_str(curproxy), curproxy->id,
7302 newsrv->id, px->id, srv->id);
7303 cfgerr++;
7304 goto next_srv;
7305 }
7306
7307 if (curproxy != px &&
7308 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7309 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7310 "tracking: disable-on-404 option inconsistency.\n",
7311 proxy_type_str(curproxy), curproxy->id,
7312 newsrv->id, px->id, srv->id);
7313 cfgerr++;
7314 goto next_srv;
7315 }
7316
7317 /* if the other server is forced disabled, we have to do the same here */
7318 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007319 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007320 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007321 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007322 }
7323
7324 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007325 newsrv->tracknext = srv->trackers;
7326 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007327
7328 free(newsrv->trackit);
7329 newsrv->trackit = NULL;
7330 }
7331 next_srv:
7332 newsrv = newsrv->next;
7333 }
7334
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007335 /* We have to initialize the server lookup mechanism depending
7336 * on what LB algorithm was choosen.
7337 */
7338
7339 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7340 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7341 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007342 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7343 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7344 init_server_map(curproxy);
7345 } else {
7346 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7347 fwrr_init_server_groups(curproxy);
7348 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007349 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007350
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007351 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007352 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7353 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7354 fwlc_init_server_tree(curproxy);
7355 } else {
7356 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7357 fas_init_server_tree(curproxy);
7358 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007359 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007360
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007361 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007362 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7363 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7364 chash_init_server_tree(curproxy);
7365 } else {
7366 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7367 init_server_map(curproxy);
7368 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007369 break;
7370 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007371
7372 if (curproxy->options & PR_O_LOGASAP)
7373 curproxy->to_log &= ~LW_BYTES;
7374
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007375 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007376 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007377 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7378 proxy_type_str(curproxy), curproxy->id);
7379 err_code |= ERR_WARN;
7380 }
7381
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007382 if (curproxy->mode != PR_MODE_HTTP) {
7383 int optnum;
7384
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007385 if (curproxy->uri_auth) {
7386 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7387 proxy_type_str(curproxy), curproxy->id);
7388 err_code |= ERR_WARN;
7389 curproxy->uri_auth = NULL;
7390 }
7391
Willy Tarreau87cf5142011-08-19 22:57:24 +02007392 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007393 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7394 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7395 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007396 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007397 }
7398
7399 if (curproxy->options & PR_O_ORGTO) {
7400 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7401 "originalto", proxy_type_str(curproxy), curproxy->id);
7402 err_code |= ERR_WARN;
7403 curproxy->options &= ~PR_O_ORGTO;
7404 }
7405
7406 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7407 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7408 (curproxy->cap & cfg_opts[optnum].cap) &&
7409 (curproxy->options & cfg_opts[optnum].val)) {
7410 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7411 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7412 err_code |= ERR_WARN;
7413 curproxy->options &= ~cfg_opts[optnum].val;
7414 }
7415 }
7416
7417 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7418 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7419 (curproxy->cap & cfg_opts2[optnum].cap) &&
7420 (curproxy->options2 & cfg_opts2[optnum].val)) {
7421 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7422 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7423 err_code |= ERR_WARN;
7424 curproxy->options2 &= ~cfg_opts2[optnum].val;
7425 }
7426 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007427
Pieter Baauwd551fb52013-05-08 22:49:23 +02007428#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007429 if (curproxy->conn_src.bind_hdr_occ) {
7430 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007431 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007432 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007433 err_code |= ERR_WARN;
7434 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007435#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007436 }
7437
Willy Tarreaubaaee002006-06-26 02:48:02 +02007438 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007439 * ensure that we're not cross-dressing a TCP server into HTTP.
7440 */
7441 newsrv = curproxy->srv;
7442 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007443 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007444 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7445 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007446 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007447 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007448
Willy Tarreau0cec3312011-10-31 13:49:26 +01007449 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7450 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7451 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7452 err_code |= ERR_WARN;
7453 }
7454
Willy Tarreau82ffa392013-08-13 17:19:08 +02007455 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7456 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7457 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7458 err_code |= ERR_WARN;
7459 }
7460
Pieter Baauwd551fb52013-05-08 22:49:23 +02007461#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007462 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7463 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007464 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 +01007465 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007466 err_code |= ERR_WARN;
7467 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007468#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007469 newsrv = newsrv->next;
7470 }
7471
Willy Tarreauc1a21672009-08-16 22:37:44 +02007472 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007473 if (!curproxy->accept)
7474 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007475
Willy Tarreauc1a21672009-08-16 22:37:44 +02007476 if (curproxy->tcp_req.inspect_delay ||
7477 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007478 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007479
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007480 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007481 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007482 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007483 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007484
7485 /* both TCP and HTTP must check switching rules */
7486 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7487 }
7488
7489 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007490 if (curproxy->tcp_req.inspect_delay ||
7491 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7492 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7493
Emeric Brun97679e72010-09-23 17:56:44 +02007494 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7495 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7496
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007497 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007498 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007499 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007500 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007501
7502 /* If the backend does requires RDP cookie persistence, we have to
7503 * enable the corresponding analyser.
7504 */
7505 if (curproxy->options2 & PR_O2_RDPC_PRST)
7506 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7507 }
7508
Emeric Brunc52962f2012-11-15 18:28:02 +01007509#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007510 /* Configure SSL for each bind line.
7511 * Note: if configuration fails at some point, the ->ctx member
7512 * remains NULL so that listeners can later detach.
7513 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007514 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007515 if (!bind_conf->is_ssl) {
7516 if (bind_conf->default_ctx) {
7517 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7518 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7519 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007520 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007521 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007522 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007523 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007524 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007525 cfgerr++;
7526 continue;
7527 }
7528
Emeric Brun4b3091e2012-09-24 15:48:52 +02007529 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007530 Alert("Unable to allocate SSL session cache.\n");
7531 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007532 continue;
7533 }
7534
Emeric Brunfc0421f2012-09-07 17:30:07 +02007535 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007536 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007537 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007538#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007539
Willy Tarreaue6b98942007-10-29 01:09:36 +01007540 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007541 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007542 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007543 if (!listener->luid) {
7544 /* listener ID not set, use automatic numbering with first
7545 * spare entry starting with next_luid.
7546 */
7547 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7548 listener->conf.id.key = listener->luid = next_id;
7549 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007550 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007551 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007552
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007553 /* enable separate counters */
7554 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7555 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007556 if (!listener->name)
7557 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007558 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007559
Willy Tarreaue6b98942007-10-29 01:09:36 +01007560 if (curproxy->options & PR_O_TCP_NOLING)
7561 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007562 if (!listener->maxconn)
7563 listener->maxconn = curproxy->maxconn;
7564 if (!listener->backlog)
7565 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007566 if (!listener->maxaccept)
7567 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7568
7569 /* we want to have an optimal behaviour on single process mode to
7570 * maximize the work at once, but in multi-process we want to keep
7571 * some fairness between processes, so we target half of the max
7572 * number of events to be balanced over all the processes the proxy
7573 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7574 * used to disable the limit.
7575 */
7576 if (listener->maxaccept > 0) {
7577 if (nbproc > 1)
7578 listener->maxaccept = (listener->maxaccept + 1) / 2;
7579 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7580 }
7581
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007582 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007583 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007584 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007585 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007586
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007587 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7588 listener->options |= LI_O_TCP_RULES;
7589
Willy Tarreaude3041d2010-05-31 10:56:17 +02007590 if (curproxy->mon_mask.s_addr)
7591 listener->options |= LI_O_CHK_MONNET;
7592
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007593 /* smart accept mode is automatic in HTTP mode */
7594 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007595 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007596 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7597 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007598 }
7599
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007600 /* Release unused SSL configs */
7601 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7602 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007603 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007604#ifdef USE_OPENSSL
7605 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007606 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007607 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007608 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007609 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007610#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007611 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007612
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007613 /* Check multi-process mode compatibility for the current proxy */
7614 if (global.nbproc > 1) {
7615 int nbproc = 0;
7616 if (curproxy->bind_proc) {
7617 int proc;
7618 for (proc = 0; proc < global.nbproc; proc++) {
7619 if (curproxy->bind_proc & (1 << proc)) {
7620 nbproc++;
7621 }
7622 }
7623 } else {
7624 nbproc = global.nbproc;
7625 }
7626 if (curproxy->table.peers.name) {
7627 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7628 curproxy->id);
7629 cfgerr++;
7630 }
7631 if (nbproc > 1) {
7632 if (curproxy->uri_auth) {
7633 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7634 curproxy->id);
7635 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7636 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7637 curproxy->id);
7638 }
7639 }
7640 if (curproxy->appsession_name) {
7641 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7642 curproxy->id);
7643 }
7644 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7645 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7646 curproxy->id);
7647 }
7648 }
7649 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007650
7651 /* create the task associated with the proxy */
7652 curproxy->task = task_new();
7653 if (curproxy->task) {
7654 curproxy->task->context = curproxy;
7655 curproxy->task->process = manage_proxy;
7656 /* no need to queue, it will be done automatically if some
7657 * listener gets limited.
7658 */
7659 curproxy->task->expire = TICK_ETERNITY;
7660 } else {
7661 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7662 curproxy->id);
7663 cfgerr++;
7664 }
7665
Willy Tarreaubaaee002006-06-26 02:48:02 +02007666 curproxy = curproxy->next;
7667 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007668
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007669 /* Check multi-process mode compatibility */
7670 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007671 if (global.stats_fe && !global.stats_fe->bind_proc) {
7672 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 +01007673 }
7674 }
7675
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007676 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7677 struct auth_users *curuser;
7678 int g;
7679
7680 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7681 unsigned int group_mask = 0;
7682 char *group = NULL;
7683
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007684 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007685 continue;
7686
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007687 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007688
7689 for (g = 0; g < curuserlist->grpcnt; g++)
7690 if (!strcmp(curuserlist->groups[g], group))
7691 break;
7692
7693 if (g == curuserlist->grpcnt) {
7694 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7695 curuserlist->name, group, curuser->user);
7696 err_code |= ERR_ALERT | ERR_FATAL;
7697 goto out;
7698 }
7699
7700 group_mask |= (1 << g);
7701 }
7702
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007703 free(curuser->u.groups);
7704 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007705 }
7706
7707 for (g = 0; g < curuserlist->grpcnt; g++) {
7708 char *user = NULL;
7709
7710 if (!curuserlist->groupusers[g])
7711 continue;
7712
7713 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7714 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7715 if (!strcmp(curuser->user, user))
7716 break;
7717
7718 if (!curuser) {
7719 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7720 curuserlist->name, user, curuserlist->groups[g]);
7721 err_code |= ERR_ALERT | ERR_FATAL;
7722 goto out;
7723 }
7724
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007725 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007726 }
7727
7728 free(curuserlist->groupusers[g]);
7729 }
7730
7731 free(curuserlist->groupusers);
7732
7733#ifdef DEBUG_AUTH
7734 for (g = 0; g < curuserlist->grpcnt; g++) {
7735 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7736
7737 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007738 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007739 fprintf(stderr, " %s", curuser->user);
7740 }
7741
7742 fprintf(stderr, "\n");
7743 }
7744#endif
7745
Willy Tarreaufbb78422011-06-05 15:38:35 +02007746 }
7747
7748 /* automatically compute fullconn if not set. We must not do it in the
7749 * loop above because cross-references are not yet fully resolved.
7750 */
7751 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7752 /* If <fullconn> is not set, let's set it to 10% of the sum of
7753 * the possible incoming frontend's maxconns.
7754 */
7755 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7756 struct proxy *fe;
7757 int total = 0;
7758
7759 /* sum up the number of maxconns of frontends which
7760 * reference this backend at least once or which are
7761 * the same one ('listen').
7762 */
7763 for (fe = proxy; fe; fe = fe->next) {
7764 struct switching_rule *rule;
7765 struct hdr_exp *exp;
7766 int found = 0;
7767
7768 if (!(fe->cap & PR_CAP_FE))
7769 continue;
7770
7771 if (fe == curproxy) /* we're on a "listen" instance */
7772 found = 1;
7773
7774 if (fe->defbe.be == curproxy) /* "default_backend" */
7775 found = 1;
7776
7777 /* check if a "use_backend" rule matches */
7778 if (!found) {
7779 list_for_each_entry(rule, &fe->switching_rules, list) {
7780 if (rule->be.backend == curproxy) {
7781 found = 1;
7782 break;
7783 }
7784 }
7785 }
7786
7787 /* check if a "reqsetbe" rule matches */
7788 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7789 if (exp->action == ACT_SETBE &&
7790 (struct proxy *)exp->replace == curproxy) {
7791 found = 1;
7792 break;
7793 }
7794 }
7795
7796 /* now we've checked all possible ways to reference a backend
7797 * from a frontend.
7798 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007799 if (!found)
7800 continue;
7801 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007802 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007803 /* we have the sum of the maxconns in <total>. We only
7804 * keep 10% of that sum to set the default fullconn, with
7805 * a hard minimum of 1 (to avoid a divide by zero).
7806 */
7807 curproxy->fullconn = (total + 9) / 10;
7808 if (!curproxy->fullconn)
7809 curproxy->fullconn = 1;
7810 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007811 }
7812
Willy Tarreau056f5682010-06-06 15:51:11 +02007813 /* initialize stick-tables on backend capable proxies. This must not
7814 * be done earlier because the data size may be discovered while parsing
7815 * other proxies.
7816 */
Godbach9703e662013-12-11 21:11:41 +08007817 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007818 if (curproxy->state == PR_STSTOPPED)
7819 continue;
7820
Godbach9703e662013-12-11 21:11:41 +08007821 if (!stktable_init(&curproxy->table)) {
7822 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7823 cfgerr++;
7824 }
7825 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007826
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007827 /*
7828 * Recount currently required checks.
7829 */
7830
7831 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7832 int optnum;
7833
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007834 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7835 if (curproxy->options & cfg_opts[optnum].val)
7836 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007837
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007838 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7839 if (curproxy->options2 & cfg_opts2[optnum].val)
7840 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007841 }
7842
Willy Tarreau122541c2011-09-07 21:24:49 +02007843 if (peers) {
7844 struct peers *curpeers = peers, **last;
7845 struct peer *p, *pb;
7846
7847 /* Remove all peers sections which don't have a valid listener.
7848 * This can happen when a peers section is never referenced and
7849 * does not contain a local peer.
7850 */
7851 last = &peers;
7852 while (*last) {
7853 curpeers = *last;
7854 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007855 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007856 last = &curpeers->next;
7857 continue;
7858 }
7859
7860 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7861 curpeers->id, localpeer);
7862
7863 p = curpeers->remote;
7864 while (p) {
7865 pb = p->next;
7866 free(p->id);
7867 free(p);
7868 p = pb;
7869 }
7870
7871 /* Destroy and unlink this curpeers section.
7872 * Note: curpeers is backed up into *last.
7873 */
7874 free(curpeers->id);
7875 curpeers = curpeers->next;
7876 free(*last);
7877 *last = curpeers;
7878 }
7879 }
7880
Willy Tarreau34eb6712011-10-24 18:15:04 +02007881 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007882 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007883 MEM_F_SHARED);
7884
Willy Tarreaubb925012009-07-23 13:36:36 +02007885 if (cfgerr > 0)
7886 err_code |= ERR_ALERT | ERR_FATAL;
7887 out:
7888 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007889}
7890
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007891/*
7892 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7893 * parsing sessions.
7894 */
7895void cfg_register_keywords(struct cfg_kw_list *kwl)
7896{
7897 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7898}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007899
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007900/*
7901 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7902 */
7903void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7904{
7905 LIST_DEL(&kwl->list);
7906 LIST_INIT(&kwl->list);
7907}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007908
7909/*
7910 * Local variables:
7911 * c-indent-level: 8
7912 * c-basic-offset: 8
7913 * End:
7914 */