blob: 5cbb9e2a6bc6f0fb78d9a678d0d18703c285076f [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100133 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100206 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100207 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
209 str = next;
210 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100211 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 *next++ = 0;
213 }
214
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100215 ss2 = str2sa_range(str, &port, &end, err,
216 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
217 if (!ss2)
218 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100220 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100221 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100226 if (!port || !end) {
227 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
228 goto fail;
229 }
230
Emeric Bruned760922010-10-22 17:59:25 +0200231 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200232 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200233 goto fail;
234 }
235
236 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200237 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200238 goto fail;
239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100241 else if (ss2->ss_family == AF_UNSPEC) {
242 socklen_t addr_len;
243
244 /* We want to attach to an already bound fd whose number
245 * is in the addr part of ss2 when cast to sockaddr_in.
246 * Note that by definition there is a single listener.
247 * We still have to determine the address family to
248 * register the correct protocol.
249 */
250 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
251 addr_len = sizeof(*ss2);
252 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
253 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
254 goto fail;
255 }
256
257 port = end = get_host_port(ss2);
258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100260 /* OK the address looks correct */
261 ss = *ss2;
262
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 for (; port <= end; port++) {
264 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100265 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau40aa0702013-03-10 23:51:38 +0100271 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200273 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100414/* Report it if a request ACL condition uses some keywords that are incompatible
415 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
416 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
417 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100419static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100420{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100421 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200422 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100425 return 0;
426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 acl = acl_cond_conflicts(cond, where);
428 if (acl) {
429 if (acl->name && *acl->name)
430 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
431 file, line, acl->name, sample_ckp_names(where));
432 else
433 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200434 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100435 return ERR_WARN;
436 }
437 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100438 return 0;
439
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100440 if (acl->name && *acl->name)
441 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200442 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 else
444 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100446 return ERR_WARN;
447}
448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200468 else if (!strcmp(args[0], "ca-base")) {
469#ifdef USE_OPENSSL
470 if (global.ca_base != NULL) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT;
473 goto out;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
479 }
480 global.ca_base = strdup(args[1]);
481#else
482 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
485#endif
486 }
487 else if (!strcmp(args[0], "crt-base")) {
488#ifdef USE_OPENSSL
489 if (global.crt_base != NULL) {
490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
491 err_code |= ERR_ALERT;
492 goto out;
493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
498 }
499 global.crt_base = strdup(args[1]);
500#else
501 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504#endif
505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200506 else if (!strcmp(args[0], "daemon")) {
507 global.mode |= MODE_DAEMON;
508 }
509 else if (!strcmp(args[0], "debug")) {
510 global.mode |= MODE_DEBUG;
511 }
512 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100513 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200515 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100521 else if (!strcmp(args[0], "nosplice")) {
522 global.tune.options &= ~GTUNE_USE_SPLICE;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 else if (!strcmp(args[0], "quiet")) {
525 global.mode |= MODE_QUIET;
526 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200527 else if (!strcmp(args[0], "tune.maxpollevents")) {
528 if (global.tune.maxpollevents != 0) {
529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 err_code |= ERR_ALERT;
531 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 }
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 global.tune.maxpollevents = atol(args[1]);
539 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100540 else if (!strcmp(args[0], "tune.maxaccept")) {
541 if (global.tune.maxaccept != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 err_code |= ERR_ALERT;
544 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 global.tune.maxaccept = atol(args[1]);
552 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200553 else if (!strcmp(args[0], "tune.chksize")) {
554 if (*(args[1]) == 0) {
555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT | ERR_FATAL;
557 goto out;
558 }
559 global.tune.chksize = atol(args[1]);
560 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200561#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100562 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.sslcachesize = atol(args[1]);
569 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100570 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
571 unsigned int ssllifetime;
572 const char *res;
573
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579
580 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
581 if (res) {
582 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
583 file, linenum, *res, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587
588 global.tune.ssllifetime = ssllifetime;
589 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100590 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.tune.ssl_max_record = atol(args[1]);
597 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200599 else if (!strcmp(args[0], "tune.bufsize")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.bufsize = atol(args[1]);
606 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
607 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100608 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100609 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200610 }
611 else if (!strcmp(args[0], "tune.maxrewrite")) {
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617 global.tune.maxrewrite = atol(args[1]);
618 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
619 global.tune.maxrewrite = global.tune.bufsize / 2;
620 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100621 else if (!strcmp(args[0], "tune.idletimer")) {
622 unsigned int idle;
623 const char *res;
624
625 if (*(args[1]) == 0) {
626 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT | ERR_FATAL;
628 goto out;
629 }
630
631 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
632 if (res) {
633 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
634 file, linenum, *res, args[0]);
635 err_code |= ERR_ALERT | ERR_FATAL;
636 goto out;
637 }
638
639 if (idle > 65535) {
640 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.idle_timer = idle;
645 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100646 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
647 if (global.tune.client_rcvbuf != 0) {
648 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
649 err_code |= ERR_ALERT;
650 goto out;
651 }
652 if (*(args[1]) == 0) {
653 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656 }
657 global.tune.client_rcvbuf = atol(args[1]);
658 }
659 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
660 if (global.tune.server_rcvbuf != 0) {
661 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
662 err_code |= ERR_ALERT;
663 goto out;
664 }
665 if (*(args[1]) == 0) {
666 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT | ERR_FATAL;
668 goto out;
669 }
670 global.tune.server_rcvbuf = atol(args[1]);
671 }
672 else if (!strcmp(args[0], "tune.sndbuf.client")) {
673 if (global.tune.client_sndbuf != 0) {
674 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
675 err_code |= ERR_ALERT;
676 goto out;
677 }
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.client_sndbuf = atol(args[1]);
684 }
685 else if (!strcmp(args[0], "tune.sndbuf.server")) {
686 if (global.tune.server_sndbuf != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT;
689 goto out;
690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
695 }
696 global.tune.server_sndbuf = atol(args[1]);
697 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200698 else if (!strcmp(args[0], "tune.pipesize")) {
699 if (*(args[1]) == 0) {
700 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704 global.tune.pipesize = atol(args[1]);
705 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100706 else if (!strcmp(args[0], "tune.http.cookielen")) {
707 if (*(args[1]) == 0) {
708 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712 global.tune.cookie_len = atol(args[1]) + 1;
713 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200714 else if (!strcmp(args[0], "tune.http.maxhdr")) {
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.max_http_hdr = atol(args[1]);
721 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100722 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
723#ifdef USE_ZLIB
724 if (*args[1]) {
725 global.tune.zlibmemlevel = atoi(args[1]);
726 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
727 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
728 file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 } else {
733 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
734 file, linenum, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738#else
739 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742#endif
743 }
744 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
745#ifdef USE_ZLIB
746 if (*args[1]) {
747 global.tune.zlibwindowsize = atoi(args[1]);
748 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
749 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
750 file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 } else {
755 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760#else
761 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764#endif
765 }
William Lallemandf3747832012-11-09 12:33:10 +0100766 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
767 if (*args[1]) {
768 global.tune.comp_maxlevel = atoi(args[1]);
769 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
770 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
771 file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 } else {
776 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
777 file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200782 else if (!strcmp(args[0], "uid")) {
783 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200784 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200785 err_code |= ERR_ALERT;
786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200787 }
788 if (*(args[1]) == 0) {
789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200792 }
793 global.uid = atol(args[1]);
794 }
795 else if (!strcmp(args[0], "gid")) {
796 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200797 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200798 err_code |= ERR_ALERT;
799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200800 }
801 if (*(args[1]) == 0) {
802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200805 }
806 global.gid = atol(args[1]);
807 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200808 /* user/group name handling */
809 else if (!strcmp(args[0], "user")) {
810 struct passwd *ha_user;
811 if (global.uid != 0) {
812 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200813 err_code |= ERR_ALERT;
814 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200815 }
816 errno = 0;
817 ha_user = getpwnam(args[1]);
818 if (ha_user != NULL) {
819 global.uid = (int)ha_user->pw_uid;
820 }
821 else {
822 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200823 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200824 }
825 }
826 else if (!strcmp(args[0], "group")) {
827 struct group *ha_group;
828 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200829 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
831 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200832 }
833 errno = 0;
834 ha_group = getgrnam(args[1]);
835 if (ha_group != NULL) {
836 global.gid = (int)ha_group->gr_gid;
837 }
838 else {
839 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200840 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200841 }
842 }
843 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200845 if (*(args[1]) == 0) {
846 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT | ERR_FATAL;
848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200849 }
850 global.nbproc = atol(args[1]);
851 }
852 else if (!strcmp(args[0], "maxconn")) {
853 if (global.maxconn != 0) {
854 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200855 err_code |= ERR_ALERT;
856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 }
858 if (*(args[1]) == 0) {
859 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200860 err_code |= ERR_ALERT | ERR_FATAL;
861 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 }
863 global.maxconn = atol(args[1]);
864#ifdef SYSTEM_MAXCONN
865 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
866 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
867 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200868 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 }
870#endif /* SYSTEM_MAXCONN */
871 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200872 else if (!strcmp(args[0], "maxsslconn")) {
873#ifdef USE_OPENSSL
874 if (*(args[1]) == 0) {
875 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
879 global.maxsslconn = atol(args[1]);
880#else
Emeric Brun0914df82012-10-02 18:45:42 +0200881 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200884#endif
885 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100886 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
887#ifdef USE_OPENSSL
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
892 }
893 free(global.listen_default_ciphers);
894 global.listen_default_ciphers = strdup(args[1]);
895#else
896 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
897 err_code |= ERR_ALERT | ERR_FATAL;
898 goto out;
899#endif
900 }
901 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
902#ifdef USE_OPENSSL
903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908 free(global.connect_default_ciphers);
909 global.connect_default_ciphers = strdup(args[1]);
910#else
911 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
912 err_code |= ERR_ALERT | ERR_FATAL;
913 goto out;
914#endif
915 }
Emeric Brun850efd52014-01-29 12:24:34 +0100916 else if (!strcmp(args[0], "ssl-server-verify")) {
917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 if (strcmp(args[1],"none") == 0)
923 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
924 else if (strcmp(args[1],"required") == 0)
925 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
926 else {
927 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200932 else if (!strcmp(args[0], "maxconnrate")) {
933 if (global.cps_lim != 0) {
934 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
935 err_code |= ERR_ALERT;
936 goto out;
937 }
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
943 global.cps_lim = atol(args[1]);
944 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200945 else if (!strcmp(args[0], "maxsessrate")) {
946 if (global.sps_lim != 0) {
947 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT;
949 goto out;
950 }
951 if (*(args[1]) == 0) {
952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
953 err_code |= ERR_ALERT | ERR_FATAL;
954 goto out;
955 }
956 global.sps_lim = atol(args[1]);
957 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200958 else if (!strcmp(args[0], "maxsslrate")) {
959 if (global.ssl_lim != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
961 err_code |= ERR_ALERT;
962 goto out;
963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
968 }
969 global.ssl_lim = atol(args[1]);
970 }
William Lallemandd85f9172012-11-09 17:05:39 +0100971 else if (!strcmp(args[0], "maxcomprate")) {
972 if (*(args[1]) == 0) {
973 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT | ERR_FATAL;
975 goto out;
976 }
977 global.comp_rate_lim = atoi(args[1]) * 1024;
978 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100979 else if (!strcmp(args[0], "maxpipes")) {
980 if (global.maxpipes != 0) {
981 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200982 err_code |= ERR_ALERT;
983 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100984 }
985 if (*(args[1]) == 0) {
986 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT | ERR_FATAL;
988 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100989 }
990 global.maxpipes = atol(args[1]);
991 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100992 else if (!strcmp(args[0], "maxzlibmem")) {
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
William Lallemande3a7d992012-11-20 11:25:20 +0100998 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100999 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001000 else if (!strcmp(args[0], "maxcompcpuusage")) {
1001 if (*(args[1]) == 0) {
1002 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001007 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001008 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012}
1013
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014 else if (!strcmp(args[0], "ulimit-n")) {
1015 if (global.rlimit_nofile != 0) {
1016 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001017 err_code |= ERR_ALERT;
1018 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001019 }
1020 if (*(args[1]) == 0) {
1021 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001024 }
1025 global.rlimit_nofile = atol(args[1]);
1026 }
1027 else if (!strcmp(args[0], "chroot")) {
1028 if (global.chroot != NULL) {
1029 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001030 err_code |= ERR_ALERT;
1031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 }
1033 if (*(args[1]) == 0) {
1034 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 global.chroot = strdup(args[1]);
1039 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001040 else if (!strcmp(args[0], "description")) {
1041 int i, len=0;
1042 char *d;
1043
1044 if (!*args[1]) {
1045 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1046 file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050
1051 for(i=1; *args[i]; i++)
1052 len += strlen(args[i])+1;
1053
1054 if (global.desc)
1055 free(global.desc);
1056
1057 global.desc = d = (char *)calloc(1, len);
1058
1059 d += sprintf(d, "%s", args[1]);
1060 for(i=2; *args[i]; i++)
1061 d += sprintf(d, " %s", args[i]);
1062 }
1063 else if (!strcmp(args[0], "node")) {
1064 int i;
1065 char c;
1066
1067 for (i=0; args[1][i]; i++) {
1068 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001069 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1070 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001071 break;
1072 }
1073
1074 if (!i || args[1][i]) {
1075 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1076 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1077 file, linenum, args[0]);
1078 err_code |= ERR_ALERT | ERR_FATAL;
1079 goto out;
1080 }
1081
1082 if (global.node)
1083 free(global.node);
1084
1085 global.node = strdup(args[1]);
1086 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 else if (!strcmp(args[0], "pidfile")) {
1088 if (global.pidfile != NULL) {
1089 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
1098 global.pidfile = strdup(args[1]);
1099 }
Emeric Bruned760922010-10-22 17:59:25 +02001100 else if (!strcmp(args[0], "unix-bind")) {
1101 int cur_arg = 1;
1102 while (*(args[cur_arg])) {
1103 if (!strcmp(args[cur_arg], "prefix")) {
1104 if (global.unix_bind.prefix != NULL) {
1105 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1106 err_code |= ERR_ALERT;
1107 cur_arg += 2;
1108 continue;
1109 }
1110
1111 if (*(args[cur_arg+1]) == 0) {
1112 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1113 err_code |= ERR_ALERT | ERR_FATAL;
1114 goto out;
1115 }
1116 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1117 cur_arg += 2;
1118 continue;
1119 }
1120
1121 if (!strcmp(args[cur_arg], "mode")) {
1122
1123 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1124 cur_arg += 2;
1125 continue;
1126 }
1127
1128 if (!strcmp(args[cur_arg], "uid")) {
1129
1130 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1131 cur_arg += 2;
1132 continue;
1133 }
1134
1135 if (!strcmp(args[cur_arg], "gid")) {
1136
1137 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1138 cur_arg += 2;
1139 continue;
1140 }
1141
1142 if (!strcmp(args[cur_arg], "user")) {
1143 struct passwd *user;
1144
1145 user = getpwnam(args[cur_arg + 1]);
1146 if (!user) {
1147 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1148 file, linenum, args[0], args[cur_arg + 1 ]);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152
1153 global.unix_bind.ux.uid = user->pw_uid;
1154 cur_arg += 2;
1155 continue;
1156 }
1157
1158 if (!strcmp(args[cur_arg], "group")) {
1159 struct group *group;
1160
1161 group = getgrnam(args[cur_arg + 1]);
1162 if (!group) {
1163 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1164 file, linenum, args[0], args[cur_arg + 1 ]);
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168
1169 global.unix_bind.ux.gid = group->gr_gid;
1170 cur_arg += 2;
1171 continue;
1172 }
1173
Willy Tarreaub48f9582011-09-05 01:17:06 +02001174 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001175 file, linenum, args[0]);
1176 err_code |= ERR_ALERT | ERR_FATAL;
1177 goto out;
1178 }
1179 }
William Lallemand0f99e342011-10-12 17:50:54 +02001180 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1181 /* delete previous herited or defined syslog servers */
1182 struct logsrv *back;
1183 struct logsrv *tmp;
1184
1185 if (*(args[1]) != 0) {
1186 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189 }
1190
1191 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1192 LIST_DEL(&tmp->list);
1193 free(tmp);
1194 }
1195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001196 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001197 struct sockaddr_storage *sk;
1198 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001199 struct logsrv *logsrv;
1200
Willy Tarreaubaaee002006-06-26 02:48:02 +02001201 if (*(args[1]) == 0 || *(args[2]) == 0) {
1202 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001203 err_code |= ERR_ALERT | ERR_FATAL;
1204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001205 }
William Lallemand0f99e342011-10-12 17:50:54 +02001206
1207 logsrv = calloc(1, sizeof(struct logsrv));
1208
1209 logsrv->facility = get_log_facility(args[2]);
1210 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001212 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001213 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001214 }
1215
William Lallemand0f99e342011-10-12 17:50:54 +02001216 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001218 logsrv->level = get_log_level(args[3]);
1219 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001220 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001221 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001222 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 }
1224 }
1225
William Lallemand0f99e342011-10-12 17:50:54 +02001226 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001227 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001228 logsrv->minlvl = get_log_level(args[4]);
1229 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001230 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001232 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001233 }
1234 }
1235
Willy Tarreau902636f2013-03-10 19:44:48 +01001236 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001237 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001238 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001239 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001240 free(logsrv);
1241 goto out;
1242 }
1243 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001244
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001245 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001246 if (port1 != port2) {
1247 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1248 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001249 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001250 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001251 goto out;
1252 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001253
William Lallemand0f99e342011-10-12 17:50:54 +02001254 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001255 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001256 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001258
William Lallemand0f99e342011-10-12 17:50:54 +02001259 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001260 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001261 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1262 char *name;
1263 int len;
1264
1265 if (global.log_send_hostname != NULL) {
1266 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT;
1268 goto out;
1269 }
1270
1271 if (*(args[1]))
1272 name = args[1];
1273 else
1274 name = hostname;
1275
1276 len = strlen(name);
1277
1278 /* We'll add a space after the name to respect the log format */
1279 free(global.log_send_hostname);
1280 global.log_send_hostname = malloc(len + 2);
1281 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1282 }
Kevinm48936af2010-12-22 16:08:21 +00001283 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1284 if (*(args[1]) == 0) {
1285 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1286 err_code |= ERR_ALERT | ERR_FATAL;
1287 goto out;
1288 }
1289 free(global.log_tag);
1290 global.log_tag = strdup(args[1]);
1291 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001292 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1293 if (global.spread_checks != 0) {
1294 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001295 err_code |= ERR_ALERT;
1296 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001297 }
1298 if (*(args[1]) == 0) {
1299 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001302 }
1303 global.spread_checks = atol(args[1]);
1304 if (global.spread_checks < 0 || global.spread_checks > 50) {
1305 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001306 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001308 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001309 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1310#ifdef USE_CPU_AFFINITY
1311 int cur_arg, i;
1312 unsigned int proc = 0;
1313 unsigned long cpus = 0;
1314
1315 if (strcmp(args[1], "all") == 0)
1316 proc = 0xFFFFFFFF;
1317 else if (strcmp(args[1], "odd") == 0)
1318 proc = 0x55555555;
1319 else if (strcmp(args[1], "even") == 0)
1320 proc = 0xAAAAAAAA;
1321 else {
1322 proc = atoi(args[1]);
1323 if (proc >= 1 && proc <= 32)
1324 proc = 1 << (proc - 1);
1325 }
1326
1327 if (!proc || !*args[2]) {
1328 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to 32, followed by a list of CPU ranges with numbers from 0 to 31.\n",
1329 file, linenum, args[0]);
1330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
1332 }
1333
1334 cur_arg = 2;
1335 while (*args[cur_arg]) {
1336 unsigned int low, high;
1337
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001338 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001339 char *dash = strchr(args[cur_arg], '-');
1340
1341 low = high = str2uic(args[cur_arg]);
1342 if (dash)
1343 high = str2uic(dash + 1);
1344
1345 if (high < low) {
1346 unsigned int swap = low;
1347 low = high;
1348 high = swap;
1349 }
1350
1351 if (low < 0 || high >= sizeof(long) * 8) {
1352 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1353 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1354 err_code |= ERR_ALERT | ERR_FATAL;
1355 goto out;
1356 }
1357
1358 while (low <= high)
1359 cpus |= 1UL << low++;
1360 }
1361 else {
1362 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1363 file, linenum, args[0], args[cur_arg]);
1364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
1366 }
1367 cur_arg++;
1368 }
1369 for (i = 0; i < 32; i++)
1370 if (proc & (1 << i))
1371 global.cpu_map[i] = cpus;
1372#else
1373 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1374 err_code |= ERR_ALERT | ERR_FATAL;
1375 goto out;
1376#endif
1377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001378 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001379 struct cfg_kw_list *kwl;
1380 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001381 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001382
1383 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1384 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1385 if (kwl->kw[index].section != CFG_GLOBAL)
1386 continue;
1387 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001388 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001389 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001390 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001392 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001393 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001394 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001395 err_code |= ERR_WARN;
1396 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001397 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001398 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001399 }
1400 }
1401 }
1402
Willy Tarreaubaaee002006-06-26 02:48:02 +02001403 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001404 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001406
Willy Tarreau058e9072009-07-20 09:30:05 +02001407 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001408 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001409 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410}
1411
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001412void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001413{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001414 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 defproxy.mode = PR_MODE_TCP;
1416 defproxy.state = PR_STNEW;
1417 defproxy.maxconn = cfg_maxpconn;
1418 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001419
Simon Horman66183002013-02-23 10:16:43 +09001420 defproxy.defsrv.check.inter = DEF_CHKINTR;
1421 defproxy.defsrv.check.fastinter = 0;
1422 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001423 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1424 defproxy.defsrv.agent.fastinter = 0;
1425 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001426 defproxy.defsrv.check.rise = DEF_RISETIME;
1427 defproxy.defsrv.check.fall = DEF_FALLTIME;
1428 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1429 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001430 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001431 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001432 defproxy.defsrv.maxqueue = 0;
1433 defproxy.defsrv.minconn = 0;
1434 defproxy.defsrv.maxconn = 0;
1435 defproxy.defsrv.slowstart = 0;
1436 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1437 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1438 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001439}
1440
Willy Tarreauade5ec42010-01-28 19:33:49 +01001441
1442static int create_cond_regex_rule(const char *file, int line,
1443 struct proxy *px, int dir, int action, int flags,
1444 const char *cmd, const char *reg, const char *repl,
1445 const char **cond_start)
1446{
1447 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001448 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001449 const char *err;
1450 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001451 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001452
1453 if (px == &defproxy) {
1454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1455 err_code |= ERR_ALERT | ERR_FATAL;
1456 goto err;
1457 }
1458
1459 if (*reg == 0) {
1460 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1461 err_code |= ERR_ALERT | ERR_FATAL;
1462 goto err;
1463 }
1464
1465 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1466 err_code |= ERR_WARN;
1467
Willy Tarreau5321c422010-01-28 20:35:13 +01001468 if (cond_start &&
1469 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001470 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1471 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1472 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001473 err_code |= ERR_ALERT | ERR_FATAL;
1474 goto err;
1475 }
1476 }
1477 else if (cond_start && **cond_start) {
1478 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1479 file, line, cmd, *cond_start);
1480 err_code |= ERR_ALERT | ERR_FATAL;
1481 goto err;
1482 }
1483
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001484 err_code |= warnif_cond_conflicts(cond,
1485 (dir == SMP_OPT_DIR_REQ) ?
1486 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1487 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1488 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001489
Willy Tarreauade5ec42010-01-28 19:33:49 +01001490 preg = calloc(1, sizeof(regex_t));
1491 if (!preg) {
1492 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1493 err_code = ERR_ALERT | ERR_FATAL;
1494 goto err;
1495 }
1496
1497 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1498 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1499 err_code = ERR_ALERT | ERR_FATAL;
1500 goto err;
1501 }
1502
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001503 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001504 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001505 if (repl && err) {
1506 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1507 file, line, cmd, *err);
1508 err_code |= ERR_ALERT | ERR_FATAL;
1509 goto err;
1510 }
1511
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001512 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001513 err_code |= ERR_WARN;
1514
Willy Tarreauf4068b62012-05-08 17:37:49 +02001515 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001516 return err_code;
1517 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001518 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001519 free(preg);
1520 return err_code;
1521}
1522
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001524 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001525 * Returns the error code, 0 if OK, or any combination of :
1526 * - ERR_ABORT: must abort ASAP
1527 * - ERR_FATAL: we can continue parsing but not start the service
1528 * - ERR_WARN: a warning has been emitted
1529 * - ERR_ALERT: an alert has been emitted
1530 * Only the two first ones can stop processing, the two others are just
1531 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001533int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1534{
1535 static struct peers *curpeers = NULL;
1536 struct peer *newpeer = NULL;
1537 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001538 struct bind_conf *bind_conf;
1539 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001540 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001541 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001542
1543 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001544 if (!*args[1]) {
1545 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001546 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001547 goto out;
1548 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001549
1550 err = invalid_char(args[1]);
1551 if (err) {
1552 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1553 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001554 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001555 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001556 }
1557
1558 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1559 /*
1560 * If there are two proxies with the same name only following
1561 * combinations are allowed:
1562 */
1563 if (strcmp(curpeers->id, args[1]) == 0) {
1564 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1565 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1566 err_code |= ERR_WARN;
1567 }
1568 }
1569
1570 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1571 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1572 err_code |= ERR_ALERT | ERR_ABORT;
1573 goto out;
1574 }
1575
1576 curpeers->next = peers;
1577 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001578 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001579 curpeers->conf.line = linenum;
1580 curpeers->last_change = now.tv_sec;
1581 curpeers->id = strdup(args[1]);
1582 }
1583 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001584 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001585 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001586 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001587
1588 if (!*args[2]) {
1589 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1590 file, linenum, args[0]);
1591 err_code |= ERR_ALERT | ERR_FATAL;
1592 goto out;
1593 }
1594
1595 err = invalid_char(args[1]);
1596 if (err) {
1597 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1598 file, linenum, *err, args[1]);
1599 err_code |= ERR_ALERT | ERR_FATAL;
1600 goto out;
1601 }
1602
1603 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1604 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1605 err_code |= ERR_ALERT | ERR_ABORT;
1606 goto out;
1607 }
1608
1609 /* the peers are linked backwards first */
1610 curpeers->count++;
1611 newpeer->next = curpeers->remote;
1612 curpeers->remote = newpeer;
1613 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001614 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001615 newpeer->conf.line = linenum;
1616
1617 newpeer->last_change = now.tv_sec;
1618 newpeer->id = strdup(args[1]);
1619
Willy Tarreau902636f2013-03-10 19:44:48 +01001620 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001621 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001622 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001623 err_code |= ERR_ALERT | ERR_FATAL;
1624 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001625 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001626
1627 proto = protocol_by_family(sk->ss_family);
1628 if (!proto || !proto->connect) {
1629 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1630 file, linenum, args[0], args[1]);
1631 err_code |= ERR_ALERT | ERR_FATAL;
1632 goto out;
1633 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001634
1635 if (port1 != port2) {
1636 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1637 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
1640 }
1641
Willy Tarreau2aa38802013-02-20 19:20:59 +01001642 if (!port1) {
1643 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1644 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001645 err_code |= ERR_ALERT | ERR_FATAL;
1646 goto out;
1647 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001648
Emeric Brun32da3c42010-09-23 18:39:19 +02001649 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001650 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001651 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001652 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001653
Emeric Brun32da3c42010-09-23 18:39:19 +02001654 if (strcmp(newpeer->id, localpeer) == 0) {
1655 /* Current is local peer, it define a frontend */
1656 newpeer->local = 1;
1657
1658 if (!curpeers->peers_fe) {
1659 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1660 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1661 err_code |= ERR_ALERT | ERR_ABORT;
1662 goto out;
1663 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001664
Willy Tarreau237250c2011-07-29 01:49:03 +02001665 init_new_proxy(curpeers->peers_fe);
1666 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001667
1668 curpeers->peers_fe->last_change = now.tv_sec;
1669 curpeers->peers_fe->id = strdup(args[1]);
1670 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001671 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001672 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1673 curpeers->peers_fe->timeout.connect = 5000;
1674 curpeers->peers_fe->accept = peer_accept;
1675 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001676 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1677 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001678
1679 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1680
Willy Tarreau902636f2013-03-10 19:44:48 +01001681 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1682 if (errmsg && *errmsg) {
1683 indent_msg(&errmsg, 2);
1684 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001685 }
1686 else
1687 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1688 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001689 err_code |= ERR_FATAL;
1690 goto out;
1691 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001692
1693 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1694 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1695 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1696 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1697 l->accept = session_accept;
1698 l->handler = process_session;
1699 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1700 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1701 global.maxsock += l->maxconn;
1702 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001703 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001704 else {
1705 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1706 file, linenum, args[0], args[1],
1707 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1708 err_code |= ERR_FATAL;
1709 goto out;
1710 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001711 }
1712 } /* neither "peer" nor "peers" */
1713 else if (*args[0] != 0) {
1714 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1715 err_code |= ERR_ALERT | ERR_FATAL;
1716 goto out;
1717 }
1718
1719out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001720 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 return err_code;
1722}
1723
Simon Horman69d29f92013-02-23 15:14:19 +09001724static int init_check(struct check *check, int type, const char * file, int linenum)
1725{
1726 check->type = type;
1727
1728 /* Allocate buffer for requests... */
1729 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1730 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1731 return ERR_ALERT | ERR_ABORT;
1732 }
1733 check->bi->size = global.tune.chksize;
1734
1735 /* Allocate buffer for responses... */
1736 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1737 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1738 return ERR_ALERT | ERR_ABORT;
1739 }
1740 check->bo->size = global.tune.chksize;
1741
1742 /* Allocate buffer for partial results... */
1743 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1744 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1745 return ERR_ALERT | ERR_ABORT;
1746 }
1747
1748 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1749
1750 return 0;
1751}
Emeric Brun32da3c42010-09-23 18:39:19 +02001752
Willy Tarreau3842f002009-06-14 11:39:52 +02001753int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754{
1755 static struct proxy *curproxy = NULL;
1756 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001757 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001758 int rc;
1759 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001760 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001761 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001762 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001763 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001764 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765
Willy Tarreau977b8e42006-12-29 14:19:17 +01001766 if (!strcmp(args[0], "listen"))
1767 rc = PR_CAP_LISTEN;
1768 else if (!strcmp(args[0], "frontend"))
1769 rc = PR_CAP_FE | PR_CAP_RS;
1770 else if (!strcmp(args[0], "backend"))
1771 rc = PR_CAP_BE | PR_CAP_RS;
1772 else if (!strcmp(args[0], "ruleset"))
1773 rc = PR_CAP_RS;
1774 else
1775 rc = PR_CAP_NONE;
1776
1777 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001778 struct ebpt_node *node;
1779
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 if (!*args[1]) {
1781 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1782 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1783 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001784 err_code |= ERR_ALERT | ERR_ABORT;
1785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001787
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001788 err = invalid_char(args[1]);
1789 if (err) {
1790 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1791 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001792 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001793 }
1794
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001795 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1796 curproxy = container_of(node, struct proxy, conf.by_name);
1797
1798 if (strcmp(curproxy->id, args[1]) != 0)
1799 break;
1800
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001801 /*
1802 * If there are two proxies with the same name only following
1803 * combinations are allowed:
1804 *
1805 * listen backend frontend ruleset
1806 * listen - - - -
1807 * backend - - OK -
1808 * frontend - OK - -
1809 * ruleset - - - -
1810 */
1811
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001812 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1813 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001814 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1815 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1816 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001817 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001818 }
1819 }
1820
Willy Tarreaubaaee002006-06-26 02:48:02 +02001821 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1822 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001823 err_code |= ERR_ALERT | ERR_ABORT;
1824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001825 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001826
Willy Tarreau97cb7802010-01-03 20:23:58 +01001827 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 curproxy->next = proxy;
1829 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001830 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1831 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001832 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001834 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001835 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836
1837 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001838 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001839 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001840
Willy Tarreau4348fad2012-09-20 16:48:07 +02001841 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1842
Willy Tarreau902636f2013-03-10 19:44:48 +01001843 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1844 if (errmsg && *errmsg) {
1845 indent_msg(&errmsg, 2);
1846 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001847 }
1848 else
1849 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1850 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001851 err_code |= ERR_FATAL;
1852 goto out;
1853 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001854
Willy Tarreau4348fad2012-09-20 16:48:07 +02001855 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001856 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001857 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001858 }
1859
1860 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001861 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001862 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001863
Willy Tarreaubaaee002006-06-26 02:48:02 +02001864 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001865 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001866 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001867 curproxy->no_options = defproxy.no_options;
1868 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001869 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001870 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001871 curproxy->except_net = defproxy.except_net;
1872 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001873 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001874 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001876 if (defproxy.fwdfor_hdr_len) {
1877 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1878 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1879 }
1880
Willy Tarreaub86db342009-11-30 11:50:16 +01001881 if (defproxy.orgto_hdr_len) {
1882 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1883 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1884 }
1885
Mark Lamourinec2247f02012-01-04 13:02:01 -05001886 if (defproxy.server_id_hdr_len) {
1887 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1888 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1889 }
1890
Willy Tarreau977b8e42006-12-29 14:19:17 +01001891 if (curproxy->cap & PR_CAP_FE) {
1892 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001893 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001894 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001895
1896 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001897 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1898 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001899
1900 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1901 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (curproxy->cap & PR_CAP_BE) {
1904 curproxy->fullconn = defproxy.fullconn;
1905 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001907 if (defproxy.check_req) {
1908 curproxy->check_req = calloc(1, defproxy.check_len);
1909 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1910 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001911 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001912
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001913 if (defproxy.expect_str) {
1914 curproxy->expect_str = strdup(defproxy.expect_str);
1915 if (defproxy.expect_regex) {
1916 /* note: this regex is known to be valid */
1917 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1918 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1919 }
1920 }
1921
Willy Tarreau67402132012-05-31 20:40:20 +02001922 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001923 if (defproxy.cookie_name)
1924 curproxy->cookie_name = strdup(defproxy.cookie_name);
1925 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001926 if (defproxy.cookie_domain)
1927 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001928
Willy Tarreau31936852010-10-06 16:59:56 +02001929 if (defproxy.cookie_maxidle)
1930 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1931
1932 if (defproxy.cookie_maxlife)
1933 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1934
Emeric Brun647caf12009-06-30 17:57:00 +02001935 if (defproxy.rdp_cookie_name)
1936 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1937 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1938
Willy Tarreau01732802007-11-01 22:48:15 +01001939 if (defproxy.url_param_name)
1940 curproxy->url_param_name = strdup(defproxy.url_param_name);
1941 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001942
Benoitaffb4812009-03-25 13:02:10 +01001943 if (defproxy.hh_name)
1944 curproxy->hh_name = strdup(defproxy.hh_name);
1945 curproxy->hh_len = defproxy.hh_len;
1946 curproxy->hh_match_domain = defproxy.hh_match_domain;
1947
Willy Tarreauef9a3602012-12-08 22:29:20 +01001948 if (defproxy.conn_src.iface_name)
1949 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1950 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001951 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001952#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001953 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001954#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001955 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001956
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001957 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001958 if (defproxy.capture_name)
1959 curproxy->capture_name = strdup(defproxy.capture_name);
1960 curproxy->capture_namelen = defproxy.capture_namelen;
1961 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963
Willy Tarreau977b8e42006-12-29 14:19:17 +01001964 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001965 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001966 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001967 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001968 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001969 curproxy->uri_auth = defproxy.uri_auth;
1970 curproxy->mon_net = defproxy.mon_net;
1971 curproxy->mon_mask = defproxy.mon_mask;
1972 if (defproxy.monitor_uri)
1973 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1974 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001975 if (defproxy.defbe.name)
1976 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001977
1978 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001979 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1980 if (curproxy->conf.logformat_string &&
1981 curproxy->conf.logformat_string != default_http_log_format &&
1982 curproxy->conf.logformat_string != default_tcp_log_format &&
1983 curproxy->conf.logformat_string != clf_http_log_format)
1984 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1985
1986 if (defproxy.conf.lfs_file) {
1987 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1988 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1989 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001990 }
1991
1992 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001993 curproxy->timeout.connect = defproxy.timeout.connect;
1994 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001995 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001996 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001997 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001998 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001999 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002000 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002001 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002002 }
2003
Willy Tarreaubaaee002006-06-26 02:48:02 +02002004 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02002005
2006 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002007 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002008 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002009 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002010 LIST_INIT(&node->list);
2011 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2012 }
2013
Willy Tarreau62a61232013-04-12 18:13:46 +02002014 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2015 if (curproxy->conf.uniqueid_format_string)
2016 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2017
2018 if (defproxy.conf.uif_file) {
2019 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2020 curproxy->conf.uif_line = defproxy.conf.uif_line;
2021 }
William Lallemanda73203e2012-03-12 12:48:57 +01002022
2023 /* copy default header unique id */
2024 if (defproxy.header_unique_id)
2025 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2026
William Lallemand82fe75c2012-10-23 10:25:10 +02002027 /* default compression options */
2028 if (defproxy.comp != NULL) {
2029 curproxy->comp = calloc(1, sizeof(struct comp));
2030 curproxy->comp->algos = defproxy.comp->algos;
2031 curproxy->comp->types = defproxy.comp->types;
2032 }
2033
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002035 curproxy->conf.used_listener_id = EB_ROOT;
2036 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002037
Willy Tarreau93893792009-07-23 13:19:11 +02002038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002039 }
2040 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2041 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002042 /* FIXME-20070101: we should do this too at the end of the
2043 * config parsing to free all default values.
2044 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002045 free(defproxy.check_req);
2046 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002047 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002048 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002049 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002050 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002051 free(defproxy.capture_name);
2052 free(defproxy.monitor_uri);
2053 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002054 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002055 free(defproxy.fwdfor_hdr_name);
2056 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002057 free(defproxy.orgto_hdr_name);
2058 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002059 free(defproxy.server_id_hdr_name);
2060 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002061 free(defproxy.expect_str);
2062 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002063
Willy Tarreau62a61232013-04-12 18:13:46 +02002064 if (defproxy.conf.logformat_string != default_http_log_format &&
2065 defproxy.conf.logformat_string != default_tcp_log_format &&
2066 defproxy.conf.logformat_string != clf_http_log_format)
2067 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002068
Willy Tarreau62a61232013-04-12 18:13:46 +02002069 free(defproxy.conf.uniqueid_format_string);
2070 free(defproxy.conf.lfs_file);
2071 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002072
Willy Tarreaua534fea2008-08-03 12:19:50 +02002073 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002074 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002075
Willy Tarreaubaaee002006-06-26 02:48:02 +02002076 /* we cannot free uri_auth because it might already be used */
2077 init_default_instance();
2078 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002079 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2080 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002081 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002083 }
2084 else if (curproxy == NULL) {
2085 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
2087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002089
2090 /* update the current file and line being parsed */
2091 curproxy->conf.args.file = curproxy->conf.file;
2092 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002093
2094 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002096 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002097 int cur_arg;
2098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (curproxy == &defproxy) {
2100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002101 err_code |= ERR_ALERT | ERR_FATAL;
2102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002104 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106
Willy Tarreau24709282013-03-10 21:32:12 +01002107 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002108 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002110 err_code |= ERR_ALERT | ERR_FATAL;
2111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002113
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002114 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002115
2116 /* use default settings for unix sockets */
2117 bind_conf->ux.uid = global.unix_bind.ux.uid;
2118 bind_conf->ux.gid = global.unix_bind.ux.gid;
2119 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002120
2121 /* NOTE: the following line might create several listeners if there
2122 * are comma-separated IPs or port ranges. So all further processing
2123 * will have to be applied to all listeners created after last_listen.
2124 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002125 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2126 if (errmsg && *errmsg) {
2127 indent_msg(&errmsg, 2);
2128 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002129 }
2130 else
2131 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2132 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
2135 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002136
Willy Tarreau4348fad2012-09-20 16:48:07 +02002137 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2138 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002139 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002140 }
2141
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002142 cur_arg = 2;
2143 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002144 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002145 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002146 char *err;
2147
Willy Tarreau26982662012-09-12 23:17:10 +02002148 kw = bind_find_kw(args[cur_arg]);
2149 if (kw) {
2150 char *err = NULL;
2151 int code;
2152
2153 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002154 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2155 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002156 cur_arg += 1 + kw->skip ;
2157 err_code |= ERR_ALERT | ERR_FATAL;
2158 goto out;
2159 }
2160
Willy Tarreau4348fad2012-09-20 16:48:07 +02002161 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002162 err_code |= code;
2163
2164 if (code) {
2165 if (err && *err) {
2166 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002167 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002168 }
2169 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002170 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2171 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002172 if (code & ERR_FATAL) {
2173 free(err);
2174 cur_arg += 1 + kw->skip;
2175 goto out;
2176 }
2177 }
2178 free(err);
2179 cur_arg += 1 + kw->skip;
2180 continue;
2181 }
2182
Willy Tarreau8638f482012-09-18 18:01:17 +02002183 err = NULL;
2184 if (!bind_dumped) {
2185 bind_dump_kws(&err);
2186 indent_msg(&err, 4);
2187 bind_dumped = 1;
2188 }
2189
2190 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2191 file, linenum, args[0], args[1], args[cur_arg],
2192 err ? " Registered keywords :" : "", err ? err : "");
2193 free(err);
2194
Willy Tarreau93893792009-07-23 13:19:11 +02002195 err_code |= ERR_ALERT | ERR_FATAL;
2196 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002197 }
Willy Tarreau93893792009-07-23 13:19:11 +02002198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002199 }
2200 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2201 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2202 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002207 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002208 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002209
Willy Tarreaubaaee002006-06-26 02:48:02 +02002210 /* flush useless bits */
2211 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002214 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002216 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217
Willy Tarreau1c47f852006-07-09 08:22:27 +02002218 if (!*args[1]) {
2219 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2220 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002221 err_code |= ERR_ALERT | ERR_FATAL;
2222 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002223 }
2224
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002226 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002227 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002228 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002229 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2230
Willy Tarreau93893792009-07-23 13:19:11 +02002231 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002232 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2234 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2235 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2236 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2237 else {
2238 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002239 err_code |= ERR_ALERT | ERR_FATAL;
2240 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002241 }
2242 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002243 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002244 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002245
2246 if (curproxy == &defproxy) {
2247 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002251 }
2252
2253 if (!*args[1]) {
2254 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2255 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002256 err_code |= ERR_ALERT | ERR_FATAL;
2257 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002258 }
2259
2260 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002261 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002262
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002263 if (curproxy->uuid <= 0) {
2264 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002265 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002266 err_code |= ERR_ALERT | ERR_FATAL;
2267 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002268 }
2269
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002270 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2271 if (node) {
2272 struct proxy *target = container_of(node, struct proxy, conf.id);
2273 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2274 file, linenum, proxy_type_str(curproxy), curproxy->id,
2275 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2276 err_code |= ERR_ALERT | ERR_FATAL;
2277 goto out;
2278 }
2279 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002280 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002281 else if (!strcmp(args[0], "description")) {
2282 int i, len=0;
2283 char *d;
2284
Cyril Bonté99ed3272010-01-24 23:29:44 +01002285 if (curproxy == &defproxy) {
2286 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2287 file, linenum, args[0]);
2288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002292 if (!*args[1]) {
2293 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2294 file, linenum, args[0]);
2295 return -1;
2296 }
2297
2298 for(i=1; *args[i]; i++)
2299 len += strlen(args[i])+1;
2300
2301 d = (char *)calloc(1, len);
2302 curproxy->desc = d;
2303
2304 d += sprintf(d, "%s", args[1]);
2305 for(i=2; *args[i]; i++)
2306 d += sprintf(d, " %s", args[i]);
2307
2308 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2310 curproxy->state = PR_STSTOPPED;
2311 }
2312 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2313 curproxy->state = PR_STNEW;
2314 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002315 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2316 int cur_arg = 1;
2317 unsigned int set = 0;
2318
2319 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002320 unsigned int low, high;
2321
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002322 if (strcmp(args[cur_arg], "all") == 0) {
2323 set = 0;
2324 break;
2325 }
2326 else if (strcmp(args[cur_arg], "odd") == 0) {
2327 set |= 0x55555555;
2328 }
2329 else if (strcmp(args[cur_arg], "even") == 0) {
2330 set |= 0xAAAAAAAA;
2331 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002332 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002333 char *dash = strchr(args[cur_arg], '-');
2334
2335 low = high = str2uic(args[cur_arg]);
2336 if (dash)
2337 high = str2uic(dash + 1);
2338
2339 if (high < low) {
2340 unsigned int swap = low;
2341 low = high;
2342 high = swap;
2343 }
2344
2345 if (low < 1 || high > 32) {
2346 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002347 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002350 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002351
2352 if (high > global.nbproc) {
2353 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2354 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002355 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002356 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002357 while (low <= high)
2358 set |= 1 << (low++ - 1);
2359 }
2360 else {
2361 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2362 file, linenum, args[0]);
2363 err_code |= ERR_ALERT | ERR_FATAL;
2364 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002365 }
2366 cur_arg++;
2367 }
2368 curproxy->bind_proc = set;
2369 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002370 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002371 if (curproxy == &defproxy) {
2372 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002375 }
2376
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002377 err = invalid_char(args[1]);
2378 if (err) {
2379 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2380 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002381 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002382 }
2383
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002384 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002385 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2386 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002389 }
2390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2392 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393
Willy Tarreau977b8e42006-12-29 14:19:17 +01002394 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002395 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002396
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 if (*(args[1]) == 0) {
2398 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2399 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002400 err_code |= ERR_ALERT | ERR_FATAL;
2401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002403
Willy Tarreau67402132012-05-31 20:40:20 +02002404 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002405 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002406 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002407 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 curproxy->cookie_name = strdup(args[1]);
2409 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002410
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 cur_arg = 2;
2412 while (*(args[cur_arg])) {
2413 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002414 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002415 }
2416 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002417 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 }
2419 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002420 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002421 }
2422 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002423 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 }
2425 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002426 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002428 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002429 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002430 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002432 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002433 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002434 else if (!strcmp(args[cur_arg], "httponly")) {
2435 curproxy->ck_opts |= PR_CK_HTTPONLY;
2436 }
2437 else if (!strcmp(args[cur_arg], "secure")) {
2438 curproxy->ck_opts |= PR_CK_SECURE;
2439 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002440 else if (!strcmp(args[cur_arg], "domain")) {
2441 if (!*args[cur_arg + 1]) {
2442 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2443 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002446 }
2447
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002448 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002449 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002450 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2451 " dots nor does not start with a dot."
2452 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002453 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002454 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002455 }
2456
2457 err = invalid_domainchar(args[cur_arg + 1]);
2458 if (err) {
2459 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2460 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002463 }
2464
Willy Tarreau68a897b2009-12-03 23:28:34 +01002465 if (!curproxy->cookie_domain) {
2466 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2467 } else {
2468 /* one domain was already specified, add another one by
2469 * building the string which will be returned along with
2470 * the cookie.
2471 */
2472 char *new_ptr;
2473 int new_len = strlen(curproxy->cookie_domain) +
2474 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2475 new_ptr = malloc(new_len);
2476 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2477 free(curproxy->cookie_domain);
2478 curproxy->cookie_domain = new_ptr;
2479 }
Willy Tarreau31936852010-10-06 16:59:56 +02002480 cur_arg++;
2481 }
2482 else if (!strcmp(args[cur_arg], "maxidle")) {
2483 unsigned int maxidle;
2484 const char *res;
2485
2486 if (!*args[cur_arg + 1]) {
2487 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2488 file, linenum, args[cur_arg]);
2489 err_code |= ERR_ALERT | ERR_FATAL;
2490 goto out;
2491 }
2492
2493 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2494 if (res) {
2495 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2496 file, linenum, *res, args[cur_arg]);
2497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
2499 }
2500 curproxy->cookie_maxidle = maxidle;
2501 cur_arg++;
2502 }
2503 else if (!strcmp(args[cur_arg], "maxlife")) {
2504 unsigned int maxlife;
2505 const char *res;
2506
2507 if (!*args[cur_arg + 1]) {
2508 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2509 file, linenum, args[cur_arg]);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
2512 }
2513
2514 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2515 if (res) {
2516 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2517 file, linenum, *res, args[cur_arg]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002522 cur_arg++;
2523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002525 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002527 err_code |= ERR_ALERT | ERR_FATAL;
2528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 }
2530 cur_arg++;
2531 }
Willy Tarreau67402132012-05-31 20:40:20 +02002532 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002533 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2534 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002535 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 }
2537
Willy Tarreau67402132012-05-31 20:40:20 +02002538 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2540 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002543
Willy Tarreau67402132012-05-31 20:40:20 +02002544 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002545 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2546 file, linenum);
2547 err_code |= ERR_ALERT | ERR_FATAL;
2548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002550 else if (!strcmp(args[0], "persist")) { /* persist */
2551 if (*(args[1]) == 0) {
2552 Alert("parsing [%s:%d] : missing persist method.\n",
2553 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002556 }
2557
2558 if (!strncmp(args[1], "rdp-cookie", 10)) {
2559 curproxy->options2 |= PR_O2_RDPC_PRST;
2560
Emeric Brunb982a3d2010-01-04 15:45:53 +01002561 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002562 const char *beg, *end;
2563
2564 beg = args[1] + 11;
2565 end = strchr(beg, ')');
2566
2567 if (!end || end == beg) {
2568 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2569 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002572 }
2573
2574 free(curproxy->rdp_cookie_name);
2575 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2576 curproxy->rdp_cookie_len = end-beg;
2577 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002578 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002579 free(curproxy->rdp_cookie_name);
2580 curproxy->rdp_cookie_name = strdup("msts");
2581 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2582 }
2583 else { /* syntax */
2584 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002588 }
2589 }
2590 else {
2591 Alert("parsing [%s:%d] : unknown persist method.\n",
2592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002595 }
2596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002598 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002600 if (curproxy == &defproxy) {
2601 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
2604 }
2605
Willy Tarreau977b8e42006-12-29 14:19:17 +01002606 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002608
Willy Tarreaubaaee002006-06-26 02:48:02 +02002609 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002610 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002611 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 }
2615 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002616 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 curproxy->appsession_name = strdup(args[1]);
2618 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2619 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002620 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2621 if (err) {
2622 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2623 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002626 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002627 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002628
Willy Tarreau51041c72007-09-09 21:56:53 +02002629 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2630 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002631 err_code |= ERR_ALERT | ERR_ABORT;
2632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002634
2635 cur_arg = 6;
2636 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002637 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2638 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002639 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002640 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002641 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002642 } else if (!strcmp(args[cur_arg], "prefix")) {
2643 curproxy->options2 |= PR_O2_AS_PFX;
2644 } else if (!strcmp(args[cur_arg], "mode")) {
2645 if (!*args[cur_arg + 1]) {
2646 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2647 file, linenum, args[0], args[cur_arg]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651
2652 cur_arg++;
2653 if (!strcmp(args[cur_arg], "query-string")) {
2654 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2655 curproxy->options2 |= PR_O2_AS_M_QS;
2656 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2657 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2658 curproxy->options2 |= PR_O2_AS_M_PP;
2659 } else {
2660 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002665 cur_arg++;
2666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 } /* Url App Session */
2668 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002669 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002673 if (curproxy == &defproxy) {
2674 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
2677 }
2678
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 if (*(args[4]) == 0) {
2680 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2681 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002685 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 curproxy->capture_name = strdup(args[2]);
2687 curproxy->capture_namelen = strlen(curproxy->capture_name);
2688 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 curproxy->to_log |= LW_COOKIE;
2690 }
2691 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2692 struct cap_hdr *hdr;
2693
2694 if (curproxy == &defproxy) {
2695 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
2699
2700 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2701 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2702 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
2706
2707 hdr = calloc(sizeof(struct cap_hdr), 1);
2708 hdr->next = curproxy->req_cap;
2709 hdr->name = strdup(args[3]);
2710 hdr->namelen = strlen(args[3]);
2711 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002712 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 hdr->index = curproxy->nb_req_cap++;
2714 curproxy->req_cap = hdr;
2715 curproxy->to_log |= LW_REQHDR;
2716 }
2717 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2718 struct cap_hdr *hdr;
2719
2720 if (curproxy == &defproxy) {
2721 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724 }
2725
2726 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2727 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2728 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 }
2732 hdr = calloc(sizeof(struct cap_hdr), 1);
2733 hdr->next = curproxy->rsp_cap;
2734 hdr->name = strdup(args[3]);
2735 hdr->namelen = strlen(args[3]);
2736 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002737 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 hdr->index = curproxy->nb_rsp_cap++;
2739 curproxy->rsp_cap = hdr;
2740 curproxy->to_log |= LW_RSPHDR;
2741 }
2742 else {
2743 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2744 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002747 }
2748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002752
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 if (*(args[1]) == 0) {
2754 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2755 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002756 err_code |= ERR_ALERT | ERR_FATAL;
2757 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 }
2759 curproxy->conn_retries = atol(args[1]);
2760 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002761 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002762 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002763
2764 if (curproxy == &defproxy) {
2765 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2766 err_code |= ERR_ALERT | ERR_FATAL;
2767 goto out;
2768 }
2769
Willy Tarreau20b0de52012-12-24 15:45:22 +01002770 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2771 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2772 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2773 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002774 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002775 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2776 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002777 file, linenum, args[0]);
2778 err_code |= ERR_WARN;
2779 }
2780
Willy Tarreauff011f22011-01-06 17:51:27 +01002781 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002782
Willy Tarreauff011f22011-01-06 17:51:27 +01002783 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002784 err_code |= ERR_ALERT | ERR_ABORT;
2785 goto out;
2786 }
2787
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002788 err_code |= warnif_cond_conflicts(rule->cond,
2789 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2790 file, linenum);
2791
Willy Tarreauff011f22011-01-06 17:51:27 +01002792 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002793 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002794 else if (!strcmp(args[0], "http-response")) { /* response access control */
2795 struct http_res_rule *rule;
2796
2797 if (curproxy == &defproxy) {
2798 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
2801 }
2802
2803 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2804 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2805 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2806 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2807 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2808 file, linenum, args[0]);
2809 err_code |= ERR_WARN;
2810 }
2811
2812 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2813
2814 if (!rule) {
2815 err_code |= ERR_ALERT | ERR_ABORT;
2816 goto out;
2817 }
2818
2819 err_code |= warnif_cond_conflicts(rule->cond,
2820 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2821 file, linenum);
2822
2823 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2824 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002825 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2826 /* set the header name and length into the proxy structure */
2827 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2828 err_code |= ERR_WARN;
2829
2830 if (!*args[1]) {
2831 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2832 file, linenum, args[0]);
2833 err_code |= ERR_ALERT | ERR_FATAL;
2834 goto out;
2835 }
2836
2837 /* set the desired header name */
2838 free(curproxy->server_id_hdr_name);
2839 curproxy->server_id_hdr_name = strdup(args[1]);
2840 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2841 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002842 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002843 if (curproxy == &defproxy) {
2844 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002847 }
2848
Willy Tarreauef6494c2010-01-28 17:12:36 +01002849 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002850 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2851 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002854 }
2855
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002856 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2857 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2858 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002861 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002862
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002863 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002864 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002865 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002866 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002867 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002868
Cyril Bonté99ed3272010-01-24 23:29:44 +01002869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002875 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002876 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2877 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002878 err_code |= ERR_ALERT | ERR_FATAL;
2879 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002880 }
2881
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002882 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002883 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002884 err_code |= warnif_cond_conflicts(rule->cond,
2885 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2886 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002887 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002888 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002889 struct switching_rule *rule;
2890
Willy Tarreaub099aca2008-10-12 17:26:37 +02002891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002895 }
2896
Willy Tarreau55ea7572007-06-17 19:56:27 +02002897 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002898 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002899
2900 if (*(args[1]) == 0) {
2901 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002904 }
2905
Willy Tarreauef6494c2010-01-28 17:12:36 +01002906 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002907 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2908 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002911 }
2912
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002913 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2914 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2915 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_ALERT | ERR_FATAL;
2917 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002918 }
2919
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002920 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002921
Willy Tarreau55ea7572007-06-17 19:56:27 +02002922 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2923 rule->cond = cond;
2924 rule->be.name = strdup(args[1]);
2925 LIST_INIT(&rule->list);
2926 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2927 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002928 else if (strcmp(args[0], "use-server") == 0) {
2929 struct server_rule *rule;
2930
2931 if (curproxy == &defproxy) {
2932 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936
2937 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2938 err_code |= ERR_WARN;
2939
2940 if (*(args[1]) == 0) {
2941 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945
2946 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2947 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2948 file, linenum, args[0]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002953 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2954 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2955 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
2959
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002960 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002961
2962 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2963 rule->cond = cond;
2964 rule->srv.name = strdup(args[1]);
2965 LIST_INIT(&rule->list);
2966 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2967 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2968 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002969 else if ((!strcmp(args[0], "force-persist")) ||
2970 (!strcmp(args[0], "ignore-persist"))) {
2971 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002972
2973 if (curproxy == &defproxy) {
2974 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2975 err_code |= ERR_ALERT | ERR_FATAL;
2976 goto out;
2977 }
2978
2979 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2980 err_code |= ERR_WARN;
2981
Willy Tarreauef6494c2010-01-28 17:12:36 +01002982 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002983 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2984 file, linenum, args[0]);
2985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
2987 }
2988
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002989 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2990 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2991 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
2994 }
2995
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002996 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2997 * where force-persist is applied.
2998 */
2999 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003000
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003001 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003002 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003003 if (!strcmp(args[0], "force-persist")) {
3004 rule->type = PERSIST_TYPE_FORCE;
3005 } else {
3006 rule->type = PERSIST_TYPE_IGNORE;
3007 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003008 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003009 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003010 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003011 else if (!strcmp(args[0], "stick-table")) {
3012 int myidx = 1;
3013
Emeric Brun32da3c42010-09-23 18:39:19 +02003014 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003015 curproxy->table.type = (unsigned int)-1;
3016 while (*args[myidx]) {
3017 const char *err;
3018
3019 if (strcmp(args[myidx], "size") == 0) {
3020 myidx++;
3021 if (!*(args[myidx])) {
3022 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3023 file, linenum, args[myidx-1]);
3024 err_code |= ERR_ALERT | ERR_FATAL;
3025 goto out;
3026 }
3027 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3028 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3029 file, linenum, *err, args[myidx-1]);
3030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
3032 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003033 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003034 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003035 else if (strcmp(args[myidx], "peers") == 0) {
3036 myidx++;
Godbach50523162013-12-11 19:48:57 +08003037 if (!*(args[myidx])) {
3038 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3039 file, linenum, args[myidx-1]);
3040 err_code |= ERR_ALERT | ERR_FATAL;
3041 goto out;
3042 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003043 curproxy->table.peers.name = strdup(args[myidx++]);
3044 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003045 else if (strcmp(args[myidx], "expire") == 0) {
3046 myidx++;
3047 if (!*(args[myidx])) {
3048 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3049 file, linenum, args[myidx-1]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
3052 }
3053 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3054 if (err) {
3055 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3056 file, linenum, *err, args[myidx-1]);
3057 err_code |= ERR_ALERT | ERR_FATAL;
3058 goto out;
3059 }
3060 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003061 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003062 }
3063 else if (strcmp(args[myidx], "nopurge") == 0) {
3064 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003065 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003066 }
3067 else if (strcmp(args[myidx], "type") == 0) {
3068 myidx++;
3069 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3070 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3071 file, linenum, args[myidx]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003075 /* myidx already points to next arg */
3076 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003077 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003078 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003079 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003080
3081 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003082 nw = args[myidx];
3083 while (*nw) {
3084 /* the "store" keyword supports a comma-separated list */
3085 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003086 sa = NULL; /* store arg */
3087 while (*nw && *nw != ',') {
3088 if (*nw == '(') {
3089 *nw = 0;
3090 sa = ++nw;
3091 while (*nw != ')') {
3092 if (!*nw) {
3093 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3094 file, linenum, args[0], cw);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
3098 nw++;
3099 }
3100 *nw = '\0';
3101 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003102 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003103 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003104 if (*nw)
3105 *nw++ = '\0';
3106 type = stktable_get_data_type(cw);
3107 if (type < 0) {
3108 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3109 file, linenum, args[0], cw);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
Willy Tarreauac782882010-06-20 10:41:54 +02003113
3114 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3115 switch (err) {
3116 case PE_NONE: break;
3117 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003118 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3119 file, linenum, args[0], cw);
3120 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003121 break;
3122
3123 case PE_ARG_MISSING:
3124 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3125 file, linenum, args[0], cw);
3126 err_code |= ERR_ALERT | ERR_FATAL;
3127 goto out;
3128
3129 case PE_ARG_NOT_USED:
3130 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3131 file, linenum, args[0], cw);
3132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
3134
3135 default:
3136 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3137 file, linenum, args[0], cw);
3138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003140 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003141 }
3142 myidx++;
3143 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003144 else {
3145 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3146 file, linenum, args[myidx]);
3147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003149 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003150 }
3151
3152 if (!curproxy->table.size) {
3153 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3154 file, linenum);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158
3159 if (curproxy->table.type == (unsigned int)-1) {
3160 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3161 file, linenum);
3162 err_code |= ERR_ALERT | ERR_FATAL;
3163 goto out;
3164 }
3165 }
3166 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003167 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003168 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003169 int myidx = 0;
3170 const char *name = NULL;
3171 int flags;
3172
3173 if (curproxy == &defproxy) {
3174 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
3178
3179 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3180 err_code |= ERR_WARN;
3181 goto out;
3182 }
3183
3184 myidx++;
3185 if ((strcmp(args[myidx], "store") == 0) ||
3186 (strcmp(args[myidx], "store-request") == 0)) {
3187 myidx++;
3188 flags = STK_IS_STORE;
3189 }
3190 else if (strcmp(args[myidx], "store-response") == 0) {
3191 myidx++;
3192 flags = STK_IS_STORE | STK_ON_RSP;
3193 }
3194 else if (strcmp(args[myidx], "match") == 0) {
3195 myidx++;
3196 flags = STK_IS_MATCH;
3197 }
3198 else if (strcmp(args[myidx], "on") == 0) {
3199 myidx++;
3200 flags = STK_IS_MATCH | STK_IS_STORE;
3201 }
3202 else {
3203 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
3206 }
3207
3208 if (*(args[myidx]) == 0) {
3209 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003214 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003215 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003216 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003217 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
3221
3222 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003223 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3224 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3225 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003226 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003227 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003228 goto out;
3229 }
3230 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003231 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3232 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3233 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003234 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003235 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003236 goto out;
3237 }
3238 }
3239
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003240 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003241 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003242
Emeric Brunb982a3d2010-01-04 15:45:53 +01003243 if (strcmp(args[myidx], "table") == 0) {
3244 myidx++;
3245 name = args[myidx++];
3246 }
3247
Willy Tarreauef6494c2010-01-28 17:12:36 +01003248 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003249 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3250 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3251 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003252 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003253 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003254 goto out;
3255 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003256 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003257 else if (*(args[myidx])) {
3258 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3259 file, linenum, args[0], args[myidx]);
3260 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003261 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003262 goto out;
3263 }
Emeric Brun97679e72010-09-23 17:56:44 +02003264 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003265 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003266 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003267 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003268
Emeric Brunb982a3d2010-01-04 15:45:53 +01003269 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3270 rule->cond = cond;
3271 rule->expr = expr;
3272 rule->flags = flags;
3273 rule->table.name = name ? strdup(name) : NULL;
3274 LIST_INIT(&rule->list);
3275 if (flags & STK_ON_RSP)
3276 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3277 else
3278 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003280 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003283
Willy Tarreaubaaee002006-06-26 02:48:02 +02003284 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3285 curproxy->uri_auth = NULL; /* we must detach from the default config */
3286
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003287 if (!*args[1]) {
3288 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003289 } else if (!strcmp(args[1], "admin")) {
3290 struct stats_admin_rule *rule;
3291
3292 if (curproxy == &defproxy) {
3293 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3294 err_code |= ERR_ALERT | ERR_FATAL;
3295 goto out;
3296 }
3297
3298 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3299 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3300 err_code |= ERR_ALERT | ERR_ABORT;
3301 goto out;
3302 }
3303
3304 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3305 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3306 file, linenum, args[0], args[1]);
3307 err_code |= ERR_ALERT | ERR_FATAL;
3308 goto out;
3309 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003310 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3311 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3312 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003317 err_code |= warnif_cond_conflicts(cond,
3318 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3319 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003320
3321 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3322 rule->cond = cond;
3323 LIST_INIT(&rule->list);
3324 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 } else if (!strcmp(args[1], "uri")) {
3326 if (*(args[2]) == 0) {
3327 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3331 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_ABORT;
3333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
3335 } else if (!strcmp(args[1], "realm")) {
3336 if (*(args[2]) == 0) {
3337 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3341 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003342 err_code |= ERR_ALERT | ERR_ABORT;
3343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003345 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003346 unsigned interval;
3347
3348 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3349 if (err) {
3350 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3351 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003354 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_ABORT;
3357 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003358 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003359 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003360 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003361
3362 if (curproxy == &defproxy) {
3363 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
3367
3368 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3369 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3370 err_code |= ERR_ALERT | ERR_ABORT;
3371 goto out;
3372 }
3373
Willy Tarreauff011f22011-01-06 17:51:27 +01003374 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3375 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003376 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3377 file, linenum, args[0]);
3378 err_code |= ERR_WARN;
3379 }
3380
Willy Tarreauff011f22011-01-06 17:51:27 +01003381 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003382
Willy Tarreauff011f22011-01-06 17:51:27 +01003383 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003384 err_code |= ERR_ALERT | ERR_ABORT;
3385 goto out;
3386 }
3387
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003388 err_code |= warnif_cond_conflicts(rule->cond,
3389 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3390 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003391 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003392
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 } else if (!strcmp(args[1], "auth")) {
3394 if (*(args[2]) == 0) {
3395 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003396 err_code |= ERR_ALERT | ERR_FATAL;
3397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_ABORT;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403 } else if (!strcmp(args[1], "scope")) {
3404 if (*(args[2]) == 0) {
3405 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003406 err_code |= ERR_ALERT | ERR_FATAL;
3407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3409 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003410 err_code |= ERR_ALERT | ERR_ABORT;
3411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003412 }
3413 } else if (!strcmp(args[1], "enable")) {
3414 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3415 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003416 err_code |= ERR_ALERT | ERR_ABORT;
3417 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003419 } else if (!strcmp(args[1], "hide-version")) {
3420 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3421 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003422 err_code |= ERR_ALERT | ERR_ABORT;
3423 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003424 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003425 } else if (!strcmp(args[1], "show-legends")) {
3426 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3427 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3428 err_code |= ERR_ALERT | ERR_ABORT;
3429 goto out;
3430 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003431 } else if (!strcmp(args[1], "show-node")) {
3432
3433 if (*args[2]) {
3434 int i;
3435 char c;
3436
3437 for (i=0; args[2][i]; i++) {
3438 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003439 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3440 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003441 break;
3442 }
3443
3444 if (!i || args[2][i]) {
3445 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3446 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3447 file, linenum, args[0], args[1]);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
3451 }
3452
3453 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3454 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3455 err_code |= ERR_ALERT | ERR_ABORT;
3456 goto out;
3457 }
3458 } else if (!strcmp(args[1], "show-desc")) {
3459 char *desc = NULL;
3460
3461 if (*args[2]) {
3462 int i, len=0;
3463 char *d;
3464
3465 for(i=2; *args[i]; i++)
3466 len += strlen(args[i])+1;
3467
3468 desc = d = (char *)calloc(1, len);
3469
3470 d += sprintf(d, "%s", args[2]);
3471 for(i=3; *args[i]; i++)
3472 d += sprintf(d, " %s", args[i]);
3473 }
3474
3475 if (!*args[2] && !global.desc)
3476 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3477 file, linenum, args[1]);
3478 else {
3479 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3480 free(desc);
3481 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3482 err_code |= ERR_ALERT | ERR_ABORT;
3483 goto out;
3484 }
3485 free(desc);
3486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003487 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003488stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003489 Alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003490 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 }
3494 }
3495 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003496 int optnum;
3497
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003498 if (*(args[1]) == '\0') {
3499 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3500 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003503 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003504
3505 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3506 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003507 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3508 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3509 file, linenum, cfg_opts[optnum].name);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
Willy Tarreau93893792009-07-23 13:19:11 +02003513 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3514 err_code |= ERR_WARN;
3515 goto out;
3516 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003517
Willy Tarreau3842f002009-06-14 11:39:52 +02003518 curproxy->no_options &= ~cfg_opts[optnum].val;
3519 curproxy->options &= ~cfg_opts[optnum].val;
3520
3521 switch (kwm) {
3522 case KWM_STD:
3523 curproxy->options |= cfg_opts[optnum].val;
3524 break;
3525 case KWM_NO:
3526 curproxy->no_options |= cfg_opts[optnum].val;
3527 break;
3528 case KWM_DEF: /* already cleared */
3529 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003530 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003531
Willy Tarreau93893792009-07-23 13:19:11 +02003532 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003533 }
3534 }
3535
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003536 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3537 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003538 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3539 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3540 file, linenum, cfg_opts2[optnum].name);
3541 err_code |= ERR_ALERT | ERR_FATAL;
3542 goto out;
3543 }
Willy Tarreau93893792009-07-23 13:19:11 +02003544 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3545 err_code |= ERR_WARN;
3546 goto out;
3547 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003548
Willy Tarreau3842f002009-06-14 11:39:52 +02003549 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3550 curproxy->options2 &= ~cfg_opts2[optnum].val;
3551
3552 switch (kwm) {
3553 case KWM_STD:
3554 curproxy->options2 |= cfg_opts2[optnum].val;
3555 break;
3556 case KWM_NO:
3557 curproxy->no_options2 |= cfg_opts2[optnum].val;
3558 break;
3559 case KWM_DEF: /* already cleared */
3560 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003561 }
Willy Tarreau93893792009-07-23 13:19:11 +02003562 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003563 }
3564 }
3565
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003566 /* HTTP options override each other. They can be cancelled using
3567 * "no option xxx" which only switches to default mode if the mode
3568 * was this one (useful for cancelling options set in defaults
3569 * sections).
3570 */
3571 if (strcmp(args[1], "httpclose") == 0) {
3572 if (kwm == KWM_STD) {
3573 curproxy->options &= ~PR_O_HTTP_MODE;
3574 curproxy->options |= PR_O_HTTP_PCL;
3575 goto out;
3576 }
3577 else if (kwm == KWM_NO) {
3578 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3579 curproxy->options &= ~PR_O_HTTP_MODE;
3580 goto out;
3581 }
3582 }
3583 else if (strcmp(args[1], "forceclose") == 0) {
3584 if (kwm == KWM_STD) {
3585 curproxy->options &= ~PR_O_HTTP_MODE;
3586 curproxy->options |= PR_O_HTTP_FCL;
3587 goto out;
3588 }
3589 else if (kwm == KWM_NO) {
3590 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3591 curproxy->options &= ~PR_O_HTTP_MODE;
3592 goto out;
3593 }
3594 }
3595 else if (strcmp(args[1], "http-server-close") == 0) {
3596 if (kwm == KWM_STD) {
3597 curproxy->options &= ~PR_O_HTTP_MODE;
3598 curproxy->options |= PR_O_HTTP_SCL;
3599 goto out;
3600 }
3601 else if (kwm == KWM_NO) {
3602 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3603 curproxy->options &= ~PR_O_HTTP_MODE;
3604 goto out;
3605 }
3606 }
3607 else if (strcmp(args[1], "http-keep-alive") == 0) {
3608 if (kwm == KWM_STD) {
3609 curproxy->options &= ~PR_O_HTTP_MODE;
3610 curproxy->options |= PR_O_HTTP_KAL;
3611 goto out;
3612 }
3613 else if (kwm == KWM_NO) {
3614 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3615 curproxy->options &= ~PR_O_HTTP_MODE;
3616 goto out;
3617 }
3618 }
3619 else if (strcmp(args[1], "http-tunnel") == 0) {
3620 if (kwm == KWM_STD) {
3621 curproxy->options &= ~PR_O_HTTP_MODE;
3622 curproxy->options |= PR_O_HTTP_TUN;
3623 goto out;
3624 }
3625 else if (kwm == KWM_NO) {
3626 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3627 curproxy->options &= ~PR_O_HTTP_MODE;
3628 goto out;
3629 }
3630 }
3631
Willy Tarreau3842f002009-06-14 11:39:52 +02003632 if (kwm != KWM_STD) {
3633 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003634 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003637 }
3638
Emeric Brun3a058f32009-06-30 18:26:00 +02003639 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003640 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003641 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003642 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003643 if (*(args[2]) != '\0') {
3644 if (!strcmp(args[2], "clf")) {
3645 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003646 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003647 } else {
3648 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003649 err_code |= ERR_ALERT | ERR_FATAL;
3650 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003651 }
3652 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003653 if (curproxy->conf.logformat_string != default_http_log_format &&
3654 curproxy->conf.logformat_string != default_tcp_log_format &&
3655 curproxy->conf.logformat_string != clf_http_log_format)
3656 free(curproxy->conf.logformat_string);
3657 curproxy->conf.logformat_string = logformat;
3658
3659 free(curproxy->conf.lfs_file);
3660 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3661 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003662 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003663 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003664 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003665 if (curproxy->conf.logformat_string != default_http_log_format &&
3666 curproxy->conf.logformat_string != default_tcp_log_format &&
3667 curproxy->conf.logformat_string != clf_http_log_format)
3668 free(curproxy->conf.logformat_string);
3669 curproxy->conf.logformat_string = default_tcp_log_format;
3670
3671 free(curproxy->conf.lfs_file);
3672 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3673 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003675 else if (!strcmp(args[1], "tcpka")) {
3676 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003677 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003678 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003679
3680 if (curproxy->cap & PR_CAP_FE)
3681 curproxy->options |= PR_O_TCP_CLI_KA;
3682 if (curproxy->cap & PR_CAP_BE)
3683 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003684 }
3685 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003686 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003687 err_code |= ERR_WARN;
3688
Willy Tarreaubaaee002006-06-26 02:48:02 +02003689 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003690 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003691 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003692 curproxy->options2 &= ~PR_O2_CHK_ANY;
3693 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 if (!*args[2]) { /* no argument */
3695 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3696 curproxy->check_len = strlen(DEF_CHECK_REQ);
3697 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003698 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 curproxy->check_req = (char *)malloc(reqlen);
3700 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003701 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003703 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 if (*args[4])
3705 reqlen += strlen(args[4]);
3706 else
3707 reqlen += strlen("HTTP/1.0");
3708
3709 curproxy->check_req = (char *)malloc(reqlen);
3710 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003711 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003713 }
3714 else if (!strcmp(args[1], "ssl-hello-chk")) {
3715 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003716 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003718
Willy Tarreaua534fea2008-08-03 12:19:50 +02003719 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003720 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003721 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003722 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
Willy Tarreau23677902007-05-08 23:50:35 +02003724 else if (!strcmp(args[1], "smtpchk")) {
3725 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003726 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003727 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003728 curproxy->options2 &= ~PR_O2_CHK_ANY;
3729 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003730
3731 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3732 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3733 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3734 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3735 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3736 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3737 curproxy->check_req = (char *)malloc(reqlen);
3738 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3739 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3740 } else {
3741 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3742 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3743 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3744 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3745 }
3746 }
3747 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003748 else if (!strcmp(args[1], "pgsql-check")) {
3749 /* use PostgreSQL request to check servers' health */
3750 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3751 err_code |= ERR_WARN;
3752
3753 free(curproxy->check_req);
3754 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003755 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003756 curproxy->options2 |= PR_O2_PGSQL_CHK;
3757
3758 if (*(args[2])) {
3759 int cur_arg = 2;
3760
3761 while (*(args[cur_arg])) {
3762 if (strcmp(args[cur_arg], "user") == 0) {
3763 char * packet;
3764 uint32_t packet_len;
3765 uint32_t pv;
3766
3767 /* suboption header - needs additional argument for it */
3768 if (*(args[cur_arg+1]) == 0) {
3769 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3770 file, linenum, args[0], args[1], args[cur_arg]);
3771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
3773 }
3774
3775 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3776 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3777 pv = htonl(0x30000); /* protocol version 3.0 */
3778
3779 packet = (char*) calloc(1, packet_len);
3780
3781 memcpy(packet + 4, &pv, 4);
3782
3783 /* copy "user" */
3784 memcpy(packet + 8, "user", 4);
3785
3786 /* copy username */
3787 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3788
3789 free(curproxy->check_req);
3790 curproxy->check_req = packet;
3791 curproxy->check_len = packet_len;
3792
3793 packet_len = htonl(packet_len);
3794 memcpy(packet, &packet_len, 4);
3795 cur_arg += 2;
3796 } else {
3797 /* unknown suboption - catchall */
3798 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3799 file, linenum, args[0], args[1]);
3800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
3802 }
3803 } /* end while loop */
3804 }
3805 }
3806
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003807 else if (!strcmp(args[1], "redis-check")) {
3808 /* use REDIS PING request to check servers' health */
3809 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3810 err_code |= ERR_WARN;
3811
3812 free(curproxy->check_req);
3813 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003814 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003815 curproxy->options2 |= PR_O2_REDIS_CHK;
3816
3817 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3818 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3819 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3820 }
3821
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003822 else if (!strcmp(args[1], "mysql-check")) {
3823 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3825 err_code |= ERR_WARN;
3826
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003827 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003828 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003829 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003830 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003831
3832 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3833 * const char mysql40_client_auth_pkt[] = {
3834 * "\x0e\x00\x00" // packet length
3835 * "\x01" // packet number
3836 * "\x00\x00" // client capabilities
3837 * "\x00\x00\x01" // max packet
3838 * "haproxy\x00" // username (null terminated string)
3839 * "\x00" // filler (always 0x00)
3840 * "\x01\x00\x00" // packet length
3841 * "\x00" // packet number
3842 * "\x01" // COM_QUIT command
3843 * };
3844 */
3845
3846 if (*(args[2])) {
3847 int cur_arg = 2;
3848
3849 while (*(args[cur_arg])) {
3850 if (strcmp(args[cur_arg], "user") == 0) {
3851 char *mysqluser;
3852 int packetlen, reqlen, userlen;
3853
3854 /* suboption header - needs additional argument for it */
3855 if (*(args[cur_arg+1]) == 0) {
3856 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3857 file, linenum, args[0], args[1], args[cur_arg]);
3858 err_code |= ERR_ALERT | ERR_FATAL;
3859 goto out;
3860 }
3861 mysqluser = args[cur_arg + 1];
3862 userlen = strlen(mysqluser);
3863 packetlen = userlen + 7;
3864 reqlen = packetlen + 9;
3865
3866 free(curproxy->check_req);
3867 curproxy->check_req = (char *)calloc(1, reqlen);
3868 curproxy->check_len = reqlen;
3869
3870 snprintf(curproxy->check_req, 4, "%c%c%c",
3871 ((unsigned char) packetlen & 0xff),
3872 ((unsigned char) (packetlen >> 8) & 0xff),
3873 ((unsigned char) (packetlen >> 16) & 0xff));
3874
3875 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003876 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003877 curproxy->check_req[8] = 1;
3878 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3879 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3880 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3881 cur_arg += 2;
3882 } else {
3883 /* unknown suboption - catchall */
3884 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3885 file, linenum, args[0], args[1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 } /* end while loop */
3890 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003891 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003892 else if (!strcmp(args[1], "ldap-check")) {
3893 /* use LDAP request to check servers' health */
3894 free(curproxy->check_req);
3895 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003896 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003897 curproxy->options2 |= PR_O2_LDAP_CHK;
3898
3899 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3900 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3901 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3902 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003903 else if (!strcmp(args[1], "tcp-check")) {
3904 /* use raw TCPCHK send/expect to check servers' health */
3905 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3906 err_code |= ERR_WARN;
3907
3908 free(curproxy->check_req);
3909 curproxy->check_req = NULL;
3910 curproxy->options2 &= ~PR_O2_CHK_ANY;
3911 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3912 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003913 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003914 int cur_arg;
3915
3916 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3917 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003918 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003919
Willy Tarreau87cf5142011-08-19 22:57:24 +02003920 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003921
3922 free(curproxy->fwdfor_hdr_name);
3923 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3924 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3925
3926 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3927 cur_arg = 2;
3928 while (*(args[cur_arg])) {
3929 if (!strcmp(args[cur_arg], "except")) {
3930 /* suboption except - needs additional argument for it */
3931 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3932 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3933 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003936 }
3937 /* flush useless bits */
3938 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003939 cur_arg += 2;
3940 } else if (!strcmp(args[cur_arg], "header")) {
3941 /* suboption header - needs additional argument for it */
3942 if (*(args[cur_arg+1]) == 0) {
3943 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3944 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003947 }
3948 free(curproxy->fwdfor_hdr_name);
3949 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3950 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3951 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003952 } else if (!strcmp(args[cur_arg], "if-none")) {
3953 curproxy->options &= ~PR_O_FF_ALWAYS;
3954 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003955 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003956 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003957 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003958 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003961 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003962 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003963 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003964 else if (!strcmp(args[1], "originalto")) {
3965 int cur_arg;
3966
3967 /* insert x-original-to field, but not for the IP address listed as an except.
3968 * set default options (ie: bitfield, header name, etc)
3969 */
3970
3971 curproxy->options |= PR_O_ORGTO;
3972
3973 free(curproxy->orgto_hdr_name);
3974 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3975 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3976
Willy Tarreau87cf5142011-08-19 22:57:24 +02003977 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003978 cur_arg = 2;
3979 while (*(args[cur_arg])) {
3980 if (!strcmp(args[cur_arg], "except")) {
3981 /* suboption except - needs additional argument for it */
3982 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3983 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3984 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003987 }
3988 /* flush useless bits */
3989 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3990 cur_arg += 2;
3991 } else if (!strcmp(args[cur_arg], "header")) {
3992 /* suboption header - needs additional argument for it */
3993 if (*(args[cur_arg+1]) == 0) {
3994 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3995 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003996 err_code |= ERR_ALERT | ERR_FATAL;
3997 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003998 }
3999 free(curproxy->orgto_hdr_name);
4000 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4001 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4002 cur_arg += 2;
4003 } else {
4004 /* unknown suboption - catchall */
4005 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4006 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004009 }
4010 } /* end while loop */
4011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004012 else {
4013 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004014 err_code |= ERR_ALERT | ERR_FATAL;
4015 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004016 }
Willy Tarreau93893792009-07-23 13:19:11 +02004017 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004018 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004019 else if (!strcmp(args[0], "default_backend")) {
4020 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004021 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004022
4023 if (*(args[1]) == 0) {
4024 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004025 err_code |= ERR_ALERT | ERR_FATAL;
4026 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004027 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004028 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004029 curproxy->defbe.name = strdup(args[1]);
4030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004031 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004032 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004033 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004034
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004035 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
4036 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004038 /* enable reconnections to dispatch */
4039 curproxy->options |= PR_O_REDISP;
4040 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004041 else if (!strcmp(args[0], "http-check")) {
4042 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004043 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004044
4045 if (strcmp(args[1], "disable-on-404") == 0) {
4046 /* enable a graceful server shutdown on an HTTP 404 response */
4047 curproxy->options |= PR_O_DISABLE404;
4048 }
Willy Tarreauef781042010-01-27 11:53:01 +01004049 else if (strcmp(args[1], "send-state") == 0) {
4050 /* enable emission of the apparent state of a server in HTTP checks */
4051 curproxy->options2 |= PR_O2_CHK_SNDST;
4052 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004053 else if (strcmp(args[1], "expect") == 0) {
4054 const char *ptr_arg;
4055 int cur_arg;
4056
4057 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4058 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4059 err_code |= ERR_ALERT | ERR_FATAL;
4060 goto out;
4061 }
4062
4063 cur_arg = 2;
4064 /* consider exclamation marks, sole or at the beginning of a word */
4065 while (*(ptr_arg = args[cur_arg])) {
4066 while (*ptr_arg == '!') {
4067 curproxy->options2 ^= PR_O2_EXP_INV;
4068 ptr_arg++;
4069 }
4070 if (*ptr_arg)
4071 break;
4072 cur_arg++;
4073 }
4074 /* now ptr_arg points to the beginning of a word past any possible
4075 * exclamation mark, and cur_arg is the argument which holds this word.
4076 */
4077 if (strcmp(ptr_arg, "status") == 0) {
4078 if (!*(args[cur_arg + 1])) {
4079 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4080 file, linenum, args[0], args[1], ptr_arg);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004085 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004086 curproxy->expect_str = strdup(args[cur_arg + 1]);
4087 }
4088 else if (strcmp(ptr_arg, "string") == 0) {
4089 if (!*(args[cur_arg + 1])) {
4090 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4091 file, linenum, args[0], args[1], ptr_arg);
4092 err_code |= ERR_ALERT | ERR_FATAL;
4093 goto out;
4094 }
4095 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004096 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004097 curproxy->expect_str = strdup(args[cur_arg + 1]);
4098 }
4099 else if (strcmp(ptr_arg, "rstatus") == 0) {
4100 if (!*(args[cur_arg + 1])) {
4101 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4102 file, linenum, args[0], args[1], ptr_arg);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004107 free(curproxy->expect_str);
4108 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4109 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004110 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4111 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4112 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4113 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4114 err_code |= ERR_ALERT | ERR_FATAL;
4115 goto out;
4116 }
4117 }
4118 else if (strcmp(ptr_arg, "rstring") == 0) {
4119 if (!*(args[cur_arg + 1])) {
4120 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4121 file, linenum, args[0], args[1], ptr_arg);
4122 err_code |= ERR_ALERT | ERR_FATAL;
4123 goto out;
4124 }
4125 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004126 free(curproxy->expect_str);
4127 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4128 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004129 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4130 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4131 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4132 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4133 err_code |= ERR_ALERT | ERR_FATAL;
4134 goto out;
4135 }
4136 }
4137 else {
4138 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4139 file, linenum, args[0], args[1], ptr_arg);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004144 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004145 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004148 }
4149 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004150 else if (!strcmp(args[0], "tcp-check")) {
4151 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4152 err_code |= ERR_WARN;
4153
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004154 if (strcmp(args[1], "connect") == 0) {
4155 const char *ptr_arg;
4156 int cur_arg;
4157 struct tcpcheck_rule *tcpcheck;
4158 struct list *l;
4159
4160 /* check if first rule is also a 'connect' action */
4161 l = (struct list *)&curproxy->tcpcheck_rules;
4162 if (l->p != l->n) {
4163 tcpcheck = (struct tcpcheck_rule *)l->n;
4164 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4165 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4166 file, linenum);
4167 err_code |= ERR_ALERT | ERR_FATAL;
4168 goto out;
4169 }
4170 }
4171
4172 cur_arg = 2;
4173 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4174 tcpcheck->action = TCPCHK_ACT_CONNECT;
4175
4176 /* parsing each parameters to fill up the rule */
4177 while (*(ptr_arg = args[cur_arg])) {
4178 /* tcp port */
4179 if (strcmp(args[cur_arg], "port") == 0) {
4180 if ( (atol(args[cur_arg + 1]) > 65535) ||
4181 (atol(args[cur_arg + 1]) < 1) ){
4182 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4183 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4184 err_code |= ERR_ALERT | ERR_FATAL;
4185 goto out;
4186 }
4187 tcpcheck->port = atol(args[cur_arg + 1]);
4188 cur_arg += 2;
4189 }
4190 /* send proxy protocol */
4191 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4192 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4193 cur_arg++;
4194 }
4195#ifdef USE_OPENSSL
4196 else if (strcmp(args[cur_arg], "ssl") == 0) {
4197 curproxy->options |= PR_O_TCPCHK_SSL;
4198 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4199 cur_arg++;
4200 }
4201#endif /* USE_OPENSSL */
4202 else {
4203#ifdef USE_OPENSSL
4204 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4205#else /* USE_OPENSSL */
4206 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4207#endif /* USE_OPENSSL */
4208 file, linenum, args[0], args[1], args[cur_arg]);
4209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
4211 }
4212
4213 }
4214
4215 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4216 }
4217 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004218 if (! *(args[2]) ) {
4219 /* SEND string expected */
4220 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4221 file, linenum, args[0], args[1], args[2]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 } else {
4225 struct tcpcheck_rule *tcpcheck;
4226
4227 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4228
4229 tcpcheck->action = TCPCHK_ACT_SEND;
4230 tcpcheck->string_len = strlen(args[2]);
4231 tcpcheck->string = strdup(args[2]);
4232 tcpcheck->expect_regex = NULL;
4233
4234 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4235 }
4236 }
4237 else if (strcmp(args[1], "send-binary") == 0) {
4238 if (! *(args[2]) ) {
4239 /* SEND binary string expected */
4240 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4241 file, linenum, args[0], args[1], args[2]);
4242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
4244 } else {
4245 struct tcpcheck_rule *tcpcheck;
4246 char *err = NULL;
4247
4248 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4249
4250 tcpcheck->action = TCPCHK_ACT_SEND;
4251 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4252 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4253 file, linenum, args[0], args[1], args[2], err);
4254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
4256 }
4257 tcpcheck->expect_regex = NULL;
4258
4259 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4260 }
4261 }
4262 else if (strcmp(args[1], "expect") == 0) {
4263 const char *ptr_arg;
4264 int cur_arg;
4265 int inverse = 0;
4266
4267 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4268 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272
4273 cur_arg = 2;
4274 /* consider exclamation marks, sole or at the beginning of a word */
4275 while (*(ptr_arg = args[cur_arg])) {
4276 while (*ptr_arg == '!') {
4277 inverse = !inverse;
4278 ptr_arg++;
4279 }
4280 if (*ptr_arg)
4281 break;
4282 cur_arg++;
4283 }
4284 /* now ptr_arg points to the beginning of a word past any possible
4285 * exclamation mark, and cur_arg is the argument which holds this word.
4286 */
4287 if (strcmp(ptr_arg, "binary") == 0) {
4288 if (!*(args[cur_arg + 1])) {
4289 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4290 file, linenum, args[0], args[1], ptr_arg);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294 struct tcpcheck_rule *tcpcheck;
4295 char *err = NULL;
4296
4297 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4298
4299 tcpcheck->action = TCPCHK_ACT_EXPECT;
4300 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4301 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4302 file, linenum, args[0], args[1], args[2], err);
4303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
4305 }
4306 tcpcheck->expect_regex = NULL;
4307 tcpcheck->inverse = inverse;
4308
4309 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4310 }
4311 else if (strcmp(ptr_arg, "string") == 0) {
4312 if (!*(args[cur_arg + 1])) {
4313 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4314 file, linenum, args[0], args[1], ptr_arg);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 struct tcpcheck_rule *tcpcheck;
4319
4320 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4321
4322 tcpcheck->action = TCPCHK_ACT_EXPECT;
4323 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4324 tcpcheck->string = strdup(args[cur_arg + 1]);
4325 tcpcheck->expect_regex = NULL;
4326 tcpcheck->inverse = inverse;
4327
4328 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4329 }
4330 else if (strcmp(ptr_arg, "rstring") == 0) {
4331 if (!*(args[cur_arg + 1])) {
4332 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4333 file, linenum, args[0], args[1], ptr_arg);
4334 err_code |= ERR_ALERT | ERR_FATAL;
4335 goto out;
4336 }
4337 struct tcpcheck_rule *tcpcheck;
4338
4339 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4340
4341 tcpcheck->action = TCPCHK_ACT_EXPECT;
4342 tcpcheck->string_len = 0;
4343 tcpcheck->string = NULL;
4344 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4345 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4346 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4347 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4348 err_code |= ERR_ALERT | ERR_FATAL;
4349 goto out;
4350 }
4351 tcpcheck->inverse = inverse;
4352
4353 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4354 }
4355 else {
4356 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4357 file, linenum, args[0], args[1], ptr_arg);
4358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
4360 }
4361 }
4362 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004363 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
4366 }
4367 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004368 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004369 if (curproxy == &defproxy) {
4370 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004373 }
4374
Willy Tarreaub80c2302007-11-30 20:51:32 +01004375 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004376 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004377
4378 if (strcmp(args[1], "fail") == 0) {
4379 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004380 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004381 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4382 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004383 err_code |= ERR_ALERT | ERR_FATAL;
4384 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004385 }
4386
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004387 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4388 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4389 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004392 }
4393 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4394 }
4395 else {
4396 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004399 }
4400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004401#ifdef TPROXY
4402 else if (!strcmp(args[0], "transparent")) {
4403 /* enable transparent proxy connections */
4404 curproxy->options |= PR_O_TRANSP;
4405 }
4406#endif
4407 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004408 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004409 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004410
Willy Tarreaubaaee002006-06-26 02:48:02 +02004411 if (*(args[1]) == 0) {
4412 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004415 }
4416 curproxy->maxconn = atol(args[1]);
4417 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004418 else if (!strcmp(args[0], "backlog")) { /* backlog */
4419 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004420 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004421
4422 if (*(args[1]) == 0) {
4423 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004424 err_code |= ERR_ALERT | ERR_FATAL;
4425 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004426 }
4427 curproxy->backlog = atol(args[1]);
4428 }
Willy Tarreau86034312006-12-29 00:10:33 +01004429 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004430 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004431 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004432
Willy Tarreau86034312006-12-29 00:10:33 +01004433 if (*(args[1]) == 0) {
4434 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004437 }
4438 curproxy->fullconn = atol(args[1]);
4439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004440 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4441 if (*(args[1]) == 0) {
4442 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004443 err_code |= ERR_ALERT | ERR_FATAL;
4444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004445 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004446 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4447 if (err) {
4448 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4449 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_ALERT | ERR_FATAL;
4451 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004452 }
4453 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 }
4455 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004456 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004457 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004458 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004459
Willy Tarreaubaaee002006-06-26 02:48:02 +02004460 if (curproxy == &defproxy) {
4461 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004465 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004467
Willy Tarreau902636f2013-03-10 19:44:48 +01004468 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004469 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004470 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004471 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004472 goto out;
4473 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004474
4475 proto = protocol_by_family(sk->ss_family);
4476 if (!proto || !proto->connect) {
4477 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4478 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004479 err_code |= ERR_ALERT | ERR_FATAL;
4480 goto out;
4481 }
4482
4483 if (port1 != port2) {
4484 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4485 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004486 err_code |= ERR_ALERT | ERR_FATAL;
4487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004488 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004489
4490 if (!port1) {
4491 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4492 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004493 err_code |= ERR_ALERT | ERR_FATAL;
4494 goto out;
4495 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004496
Willy Tarreaud5191e72010-02-09 20:50:45 +01004497 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004498 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 }
4500 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004501 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004502 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004503
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004504 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4505 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004510 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004511 /**
4512 * The syntax for hash-type config element is
4513 * hash-type {map-based|consistent} [[<algo>] avalanche]
4514 *
4515 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4516 */
4517 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004518
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004519 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4520 err_code |= ERR_WARN;
4521
4522 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004523 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4524 }
4525 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004526 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4527 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004528 else if (strcmp(args[1], "avalanche") == 0) {
4529 Alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
4530 err_code |= ERR_ALERT | ERR_FATAL;
4531 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004532 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004533 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004534 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
Bhaskar98634f02013-10-29 23:30:51 -04004538
4539 /* set the hash function to use */
4540 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004541 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004542 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004543
4544 /* if consistent with no argument, then avalanche modifier is also applied */
4545 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4546 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004547 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004548 /* set the hash function */
4549 if (!strcmp(args[2], "sdbm")) {
4550 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4551 }
4552 else if (!strcmp(args[2], "djb2")) {
4553 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004554 } else if (!strcmp(args[2], "wt6")) {
4555 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004556 }
4557 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004558 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2' or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004559 err_code |= ERR_ALERT | ERR_FATAL;
4560 goto out;
4561 }
4562
4563 /* set the hash modifier */
4564 if (!strcmp(args[3], "avalanche")) {
4565 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4566 }
4567 else if (*args[3]) {
4568 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4569 err_code |= ERR_ALERT | ERR_FATAL;
4570 goto out;
4571 }
Bhaskar98634f02013-10-29 23:30:51 -04004572 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004573 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004574 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004576 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004577 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004579 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004580 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004581 err_code |= ERR_ALERT | ERR_FATAL;
4582 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004583 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004584 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004586
4587 if (!*args[2]) {
4588 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4589 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004593
4594 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004595 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004596 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4597 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004598 err_code |= ERR_ALERT | ERR_FATAL;
4599 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004600 }
4601
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004602 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004603 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004604 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004605 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004606
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004607 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4608 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4609 err_code |= ERR_ALERT | ERR_ABORT;
4610 goto out;
4611 }
4612
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004613 /* the servers are linked backwards first */
4614 newsrv->next = curproxy->srv;
4615 curproxy->srv = newsrv;
4616 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004617 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004618 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004620 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004621 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004622 LIST_INIT(&newsrv->pendconns);
4623 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004624 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004625 newsrv->state = SRV_RUNNING; /* early server setup */
4626 newsrv->last_change = now.tv_sec;
4627 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004628
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004629 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004630 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004631 * - IP: => port=+0, relative
4632 * - IP:N => port=N, absolute
4633 * - IP:+N => port=+N, relative
4634 * - IP:-N => port=-N, relative
4635 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004636 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004637 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004638 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004639 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004640 goto out;
4641 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004642
4643 proto = protocol_by_family(sk->ss_family);
4644 if (!proto || !proto->connect) {
4645 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4646 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
4649 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004650
4651 if (!port1 || !port2) {
4652 /* no port specified, +offset, -offset */
4653 newsrv->state |= SRV_MAPPORTS;
4654 }
4655 else if (port1 != port2) {
4656 /* port range */
4657 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4658 file, linenum, args[0], args[1], args[2]);
4659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
4661 }
4662 else {
4663 /* used by checks */
4664 realport = port1;
4665 }
4666
Willy Tarreaud5191e72010-02-09 20:50:45 +01004667 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004668 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4669 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004670
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004671 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004672 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4673 file, linenum, newsrv->addr.ss_family, args[2]);
4674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
4676 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004677
Simon Hormand60d6912013-11-25 10:46:36 +09004678 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004679 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004680 newsrv->check.inter = curproxy->defsrv.check.inter;
4681 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4682 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004683 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4684 newsrv->agent.port = curproxy->defsrv.agent.port;
4685 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4686 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4687 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004688 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4689 newsrv->minconn = curproxy->defsrv.minconn;
4690 newsrv->maxconn = curproxy->defsrv.maxconn;
4691 newsrv->slowstart = curproxy->defsrv.slowstart;
4692 newsrv->onerror = curproxy->defsrv.onerror;
Willy Tarreauabd03df2014-02-18 10:36:15 +01004693 newsrv->onmarkeddown = curproxy->defsrv.onmarkeddown;
4694 newsrv->onmarkedup = curproxy->defsrv.onmarkedup;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004695 newsrv->consecutive_errors_limit
4696 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004697#ifdef OPENSSL
4698 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4699#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004700 newsrv->uweight = newsrv->iweight
4701 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702
Simon Horman69d29f92013-02-23 15:14:19 +09004703 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004704 newsrv->check.rise = curproxy->defsrv.check.rise;
4705 newsrv->check.fall = curproxy->defsrv.check.fall;
4706 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004707 newsrv->check.server = newsrv;
4708
Simon Hormand60d6912013-11-25 10:46:36 +09004709 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004710 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4711 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4712 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004713 newsrv->agent.server = newsrv;
4714
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004715 cur_arg = 3;
4716 } else {
4717 newsrv = &curproxy->defsrv;
4718 cur_arg = 1;
4719 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004720
Willy Tarreaubaaee002006-06-26 02:48:02 +02004721 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004722 if (!strcmp(args[cur_arg], "agent-check")) {
4723 global.maxsock++;
4724 do_agent = 1;
4725 cur_arg += 1;
4726 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4727 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4728 if (err) {
4729 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4730 file, linenum, *err, newsrv->id);
4731 err_code |= ERR_ALERT | ERR_FATAL;
4732 goto out;
4733 }
4734 if (val <= 0) {
4735 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4736 file, linenum, val, args[cur_arg], newsrv->id);
4737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
4740 newsrv->agent.inter = val;
4741 cur_arg += 2;
4742 }
4743 else if (!strcmp(args[cur_arg], "agent-port")) {
4744 global.maxsock++;
4745 newsrv->agent.port = atol(args[cur_arg + 1]);
4746 cur_arg += 2;
4747 }
4748 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 newsrv->cookie = strdup(args[cur_arg + 1]);
4750 newsrv->cklen = strlen(args[cur_arg + 1]);
4751 cur_arg += 2;
4752 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004753 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004754 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4755 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4756 cur_arg += 2;
4757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004758 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004759 if (!*args[cur_arg + 1]) {
4760 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4761 file, linenum, args[cur_arg]);
4762 err_code |= ERR_ALERT | ERR_FATAL;
4763 goto out;
4764 }
4765
Simon Horman58c32972013-11-25 10:46:38 +09004766 newsrv->check.rise = atol(args[cur_arg + 1]);
4767 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004768 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4769 file, linenum, args[cur_arg]);
4770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
4772 }
4773
Simon Horman125d0992013-02-24 17:23:38 +09004774 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004775 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004776 cur_arg += 2;
4777 }
4778 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004779 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004780
4781 if (!*args[cur_arg + 1]) {
4782 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4783 file, linenum, args[cur_arg]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786 }
4787
Simon Horman58c32972013-11-25 10:46:38 +09004788 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004789 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4790 file, linenum, args[cur_arg]);
4791 err_code |= ERR_ALERT | ERR_FATAL;
4792 goto out;
4793 }
4794
Willy Tarreaubaaee002006-06-26 02:48:02 +02004795 cur_arg += 2;
4796 }
4797 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004798 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4799 if (err) {
4800 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4801 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004804 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004805 if (val <= 0) {
4806 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4807 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004810 }
Simon Horman66183002013-02-23 10:16:43 +09004811 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 cur_arg += 2;
4813 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004814 else if (!strcmp(args[cur_arg], "fastinter")) {
4815 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4816 if (err) {
4817 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4818 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004821 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004822 if (val <= 0) {
4823 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4824 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004825 err_code |= ERR_ALERT | ERR_FATAL;
4826 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004827 }
Simon Horman66183002013-02-23 10:16:43 +09004828 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004829 cur_arg += 2;
4830 }
4831 else if (!strcmp(args[cur_arg], "downinter")) {
4832 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4833 if (err) {
4834 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4835 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004838 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004839 if (val <= 0) {
4840 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4841 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004844 }
Simon Horman66183002013-02-23 10:16:43 +09004845 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004846 cur_arg += 2;
4847 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004848 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004849 struct sockaddr_storage *sk;
4850 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004851 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004852
Willy Tarreau902636f2013-03-10 19:44:48 +01004853 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004854 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004855 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004856 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004857 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004858 goto out;
4859 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004860
4861 proto = protocol_by_family(sk->ss_family);
4862 if (!proto || !proto->connect) {
4863 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004864 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004868
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004869 if (port1 != port2) {
4870 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4871 file, linenum, args[cur_arg], args[cur_arg + 1]);
4872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
4874 }
4875
Simon Horman66183002013-02-23 10:16:43 +09004876 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004877 cur_arg += 2;
4878 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004879 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004880 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 cur_arg += 2;
4882 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004883 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 newsrv->state |= SRV_BACKUP;
4885 cur_arg ++;
4886 }
Simon Hormanfa461682011-06-25 09:39:49 +09004887 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4888 newsrv->state |= SRV_NON_STICK;
4889 cur_arg ++;
4890 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004891 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4892 newsrv->state |= SRV_SEND_PROXY;
4893 cur_arg ++;
4894 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004895 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4896 newsrv->check.send_proxy = 1;
4897 cur_arg ++;
4898 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004899 else if (!strcmp(args[cur_arg], "weight")) {
4900 int w;
4901 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004902 if (w < 0 || w > SRV_UWGHT_MAX) {
4903 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4904 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004907 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004908 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909 cur_arg += 2;
4910 }
4911 else if (!strcmp(args[cur_arg], "minconn")) {
4912 newsrv->minconn = atol(args[cur_arg + 1]);
4913 cur_arg += 2;
4914 }
4915 else if (!strcmp(args[cur_arg], "maxconn")) {
4916 newsrv->maxconn = atol(args[cur_arg + 1]);
4917 cur_arg += 2;
4918 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004919 else if (!strcmp(args[cur_arg], "maxqueue")) {
4920 newsrv->maxqueue = atol(args[cur_arg + 1]);
4921 cur_arg += 2;
4922 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004923 else if (!strcmp(args[cur_arg], "slowstart")) {
4924 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004925 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004926 if (err) {
4927 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4928 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004931 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004932 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004933 cur_arg += 2;
4934 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004935 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004936
4937 if (!*args[cur_arg + 1]) {
4938 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4939 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004942 }
4943
4944 newsrv->trackit = strdup(args[cur_arg + 1]);
4945
4946 cur_arg += 2;
4947 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004948 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004949 global.maxsock++;
4950 do_check = 1;
4951 cur_arg += 1;
4952 }
Willy Tarreau96839092010-03-29 10:02:24 +02004953 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4954 newsrv->state |= SRV_MAINTAIN;
4955 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004956 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004957 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004958 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004959 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004960 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004961 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004962 if (!strcmp(args[cur_arg + 1], "none"))
4963 newsrv->observe = HANA_OBS_NONE;
4964 else if (!strcmp(args[cur_arg + 1], "layer4"))
4965 newsrv->observe = HANA_OBS_LAYER4;
4966 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4967 if (curproxy->mode != PR_MODE_HTTP) {
4968 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4969 file, linenum, args[cur_arg + 1]);
4970 err_code |= ERR_ALERT;
4971 }
4972 newsrv->observe = HANA_OBS_LAYER7;
4973 }
4974 else {
4975 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004976 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004977 file, linenum, args[cur_arg], args[cur_arg + 1]);
4978 err_code |= ERR_ALERT | ERR_FATAL;
4979 goto out;
4980 }
4981
4982 cur_arg += 2;
4983 }
4984 else if (!strcmp(args[cur_arg], "on-error")) {
4985 if (!strcmp(args[cur_arg + 1], "fastinter"))
4986 newsrv->onerror = HANA_ONERR_FASTINTER;
4987 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4988 newsrv->onerror = HANA_ONERR_FAILCHK;
4989 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4990 newsrv->onerror = HANA_ONERR_SUDDTH;
4991 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4992 newsrv->onerror = HANA_ONERR_MARKDWN;
4993 else {
4994 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004995 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004996 file, linenum, args[cur_arg], args[cur_arg + 1]);
4997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
4999 }
5000
5001 cur_arg += 2;
5002 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09005003 else if (!strcmp(args[cur_arg], "on-marked-down")) {
5004 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
5005 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
5006 else {
5007 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
5008 file, linenum, args[cur_arg], args[cur_arg + 1]);
5009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
5011 }
5012
5013 cur_arg += 2;
5014 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07005015 else if (!strcmp(args[cur_arg], "on-marked-up")) {
5016 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
5017 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
5018 else {
5019 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
5020 file, linenum, args[cur_arg], args[cur_arg + 1]);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
5024
5025 cur_arg += 2;
5026 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005027 else if (!strcmp(args[cur_arg], "error-limit")) {
5028 if (!*args[cur_arg + 1]) {
5029 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
5030 file, linenum, args[cur_arg]);
5031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
5033 }
5034
5035 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
5036
5037 if (newsrv->consecutive_errors_limit <= 0) {
5038 Alert("parsing [%s:%d]: %s has to be > 0.\n",
5039 file, linenum, args[cur_arg]);
5040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
5042 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01005043 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01005044 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005045 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005046 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005047 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005048 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01005049
Willy Tarreaubaaee002006-06-26 02:48:02 +02005050 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01005051 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
5052 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005056
Willy Tarreauef9a3602012-12-08 22:29:20 +01005057 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01005058 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005059 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005060 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005061 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005062 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005063 goto out;
5064 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005065
5066 proto = protocol_by_family(sk->ss_family);
5067 if (!proto || !proto->connect) {
5068 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5069 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005070 err_code |= ERR_ALERT | ERR_FATAL;
5071 goto out;
5072 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005073
Willy Tarreauef9a3602012-12-08 22:29:20 +01005074 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005075
5076 if (port_low != port_high) {
5077 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005078
5079 if (!port_low || !port_high) {
5080 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
5081 file, linenum, args[cur_arg], args[cur_arg + 1]);
5082 err_code |= ERR_ALERT | ERR_FATAL;
5083 goto out;
5084 }
5085
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005086 if (port_low <= 0 || port_low > 65535 ||
5087 port_high <= 0 || port_high > 65535 ||
5088 port_low > port_high) {
5089 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
5090 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005093 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005094 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
5095 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
5096 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02005097 }
5098
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005100 while (*(args[cur_arg])) {
5101 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005102#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5103#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005104 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01005105 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
5106 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005109 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005110#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005111 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005112 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01005113 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005116 }
5117 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005118 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5119 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005120 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005121 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5122 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005123 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5124 char *name, *end;
5125
5126 name = args[cur_arg+1] + 7;
5127 while (isspace(*name))
5128 name++;
5129
5130 end = name;
5131 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5132 end++;
5133
Willy Tarreauef9a3602012-12-08 22:29:20 +01005134 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5135 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5136 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5137 newsrv->conn_src.bind_hdr_len = end - name;
5138 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5139 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5140 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005141
5142 /* now look for an occurrence number */
5143 while (isspace(*end))
5144 end++;
5145 if (*end == ',') {
5146 end++;
5147 name = end;
5148 if (*end == '-')
5149 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005150 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005151 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005152 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005153 }
5154
Willy Tarreauef9a3602012-12-08 22:29:20 +01005155 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005156 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5157 " occurrences values smaller than %d.\n",
5158 file, linenum, MAX_HDR_HISTORY);
5159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
5161 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005162 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005163 struct sockaddr_storage *sk;
5164 int port1, port2;
5165
Willy Tarreau902636f2013-03-10 19:44:48 +01005166 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005167 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005168 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005169 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005170 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005171 goto out;
5172 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005173
5174 proto = protocol_by_family(sk->ss_family);
5175 if (!proto || !proto->connect) {
5176 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5177 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
5180 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005181
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005182 if (port1 != port2) {
5183 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5184 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
5187 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005188 newsrv->conn_src.tproxy_addr = *sk;
5189 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005190 }
5191 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005192#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005193 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005194#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005195 cur_arg += 2;
5196 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005197#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005198 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005199 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005202#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005203 } /* "usesrc" */
5204
5205 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5206#ifdef SO_BINDTODEVICE
5207 if (!*args[cur_arg + 1]) {
5208 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5209 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005210 err_code |= ERR_ALERT | ERR_FATAL;
5211 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005212 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005213 free(newsrv->conn_src.iface_name);
5214 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5215 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005216 global.last_checks |= LSTCHK_NETADM;
5217#else
5218 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5219 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005220 err_code |= ERR_ALERT | ERR_FATAL;
5221 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005222#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005223 cur_arg += 2;
5224 continue;
5225 }
5226 /* this keyword in not an option of "source" */
5227 break;
5228 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005230 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005231 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5232 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005233 err_code |= ERR_ALERT | ERR_FATAL;
5234 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005237 static int srv_dumped;
5238 struct srv_kw *kw;
5239 char *err;
5240
5241 kw = srv_find_kw(args[cur_arg]);
5242 if (kw) {
5243 char *err = NULL;
5244 int code;
5245
5246 if (!kw->parse) {
5247 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5248 file, linenum, args[0], args[1], args[cur_arg]);
5249 cur_arg += 1 + kw->skip ;
5250 err_code |= ERR_ALERT | ERR_FATAL;
5251 goto out;
5252 }
5253
5254 if (defsrv && !kw->default_ok) {
5255 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5256 file, linenum, args[0], args[1], args[cur_arg]);
5257 cur_arg += 1 + kw->skip ;
5258 err_code |= ERR_ALERT;
5259 continue;
5260 }
5261
5262 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5263 err_code |= code;
5264
5265 if (code) {
5266 if (err && *err) {
5267 indent_msg(&err, 2);
5268 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5269 }
5270 else
5271 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5272 file, linenum, args[0], args[1], args[cur_arg]);
5273 if (code & ERR_FATAL) {
5274 free(err);
5275 cur_arg += 1 + kw->skip;
5276 goto out;
5277 }
5278 }
5279 free(err);
5280 cur_arg += 1 + kw->skip;
5281 continue;
5282 }
5283
5284 err = NULL;
5285 if (!srv_dumped) {
5286 srv_dump_kws(&err);
5287 indent_msg(&err, 4);
5288 srv_dumped = 1;
5289 }
5290
5291 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5292 file, linenum, args[0], args[1], args[cur_arg],
5293 err ? " Registered keywords :" : "", err ? err : "");
5294 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005295
Willy Tarreau93893792009-07-23 13:19:11 +02005296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005298 }
5299 }
5300
Simon Horman8c3d0be2013-11-25 10:46:40 +09005301 /* Set initial drain state using now-configured weight */
5302 set_server_drain_state(newsrv);
5303
Willy Tarreaubaaee002006-06-26 02:48:02 +02005304 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005305 int ret;
5306
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005307 if (newsrv->trackit) {
5308 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5309 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005312 }
5313
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005314 /* If neither a port nor an addr was specified and no check transport
5315 * layer is forced, then the transport layer used by the checks is the
5316 * same as for the production traffic. Otherwise we use raw_sock by
5317 * default, unless one is specified.
5318 */
Simon Horman66183002013-02-23 10:16:43 +09005319 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005320#ifdef USE_OPENSSL
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005321 newsrv->check.use_ssl |= (newsrv->use_ssl || (newsrv->proxy->options & PR_O_TCPCHK_SSL));
Willy Tarreau71516332012-10-10 23:01:14 +02005322#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005323 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5324 }
Simon Horman66183002013-02-23 10:16:43 +09005325 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005326 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005327 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005328
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005329 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005330 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005331
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005332 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005333 /* not yet valid, because no port was set on
5334 * the server either. We'll check if we have
5335 * a known port on the first listener.
5336 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005337 struct listener *l;
5338
5339 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005340 newsrv->check.port = get_host_port(&l->addr);
5341 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005342 break;
5343 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005344 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005345 /*
5346 * We need at least a service port, a check port or the first tcp-check rule must
5347 * be a 'connect' one
5348 */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005349 if (!newsrv->check.port) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005350 struct tcpcheck_rule *n = NULL, *r = NULL;
5351 struct list *l;
5352
5353 r = (struct tcpcheck_rule *)newsrv->proxy->tcpcheck_rules.n;
5354 if (!r) {
5355 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5356 file, linenum, newsrv->id);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360 if ((r->action != TCPCHK_ACT_CONNECT) || !r->port) {
5361 Alert("parsing [%s:%d] : server %s has neither service port nor check port nor tcp_check rule 'connect' with port information. Check has been disabled.\n",
5362 file, linenum, newsrv->id);
5363 err_code |= ERR_ALERT | ERR_FATAL;
5364 goto out;
5365 }
5366 else {
5367 /* scan the tcp-check ruleset to ensure a port has been configured */
5368 l = &newsrv->proxy->tcpcheck_rules;
5369 list_for_each_entry(n, l, list) {
5370 r = (struct tcpcheck_rule *)n->list.p;
5371 if ((r->action == TCPCHK_ACT_CONNECT) && (!r->port)) {
5372 Alert("parsing [%s:%d] : server %s has neither service port nor check port, and a tcp_check rule 'connect' with no port information. Check has been disabled.\n",
5373 file, linenum, newsrv->id);
5374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376 }
5377 }
5378 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005379 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005380
Willy Tarreau2f075e92013-12-03 11:11:34 +01005381 /* note: check type will be set during the config review phase */
5382 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005383 if (ret) {
5384 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005385 goto out;
5386 }
5387
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005388 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
5390
Simon Hormand60d6912013-11-25 10:46:36 +09005391 if (do_agent) {
5392 int ret;
5393
5394 if (!newsrv->agent.port) {
5395 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5396 file, linenum, newsrv->id);
5397 err_code |= ERR_ALERT | ERR_FATAL;
5398 goto out;
5399 }
5400
5401 if (!newsrv->agent.inter)
5402 newsrv->agent.inter = newsrv->check.inter;
5403
5404 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5405 if (ret) {
5406 err_code |= ret;
5407 goto out;
5408 }
5409
Willy Tarreau33434322013-12-11 21:15:19 +01005410 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005411 }
5412
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005413 if (!defsrv) {
5414 if (newsrv->state & SRV_BACKUP)
5415 curproxy->srv_bck++;
5416 else
5417 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005418
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005419 newsrv->prev_state = newsrv->state;
5420 }
William Lallemanda73203e2012-03-12 12:48:57 +01005421 }
5422
5423 else if (strcmp(args[0], "unique-id-format") == 0) {
5424 if (!*(args[1])) {
5425 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
5428 }
William Lallemand3203ff42012-11-11 17:30:56 +01005429 if (*(args[2])) {
5430 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
5433 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005434 free(curproxy->conf.uniqueid_format_string);
5435 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005436
Willy Tarreau62a61232013-04-12 18:13:46 +02005437 free(curproxy->conf.uif_file);
5438 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5439 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005440 }
William Lallemanda73203e2012-03-12 12:48:57 +01005441
5442 else if (strcmp(args[0], "unique-id-header") == 0) {
5443 if (!*(args[1])) {
5444 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5445 err_code |= ERR_ALERT | ERR_FATAL;
5446 goto out;
5447 }
5448 free(curproxy->header_unique_id);
5449 curproxy->header_unique_id = strdup(args[1]);
5450 }
5451
William Lallemand723b73a2012-02-08 16:37:49 +01005452 else if (strcmp(args[0], "log-format") == 0) {
5453 if (!*(args[1])) {
5454 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
William Lallemand3203ff42012-11-11 17:30:56 +01005458 if (*(args[2])) {
5459 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
5462 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005463
Willy Tarreau62a61232013-04-12 18:13:46 +02005464 if (curproxy->conf.logformat_string != default_http_log_format &&
5465 curproxy->conf.logformat_string != default_tcp_log_format &&
5466 curproxy->conf.logformat_string != clf_http_log_format)
5467 free(curproxy->conf.logformat_string);
5468 curproxy->conf.logformat_string = strdup(args[1]);
5469
5470 free(curproxy->conf.lfs_file);
5471 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5472 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005473
5474 /* get a chance to improve log-format error reporting by
5475 * reporting the correct line-number when possible.
5476 */
5477 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5478 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5479 file, linenum, curproxy->id);
5480 err_code |= ERR_WARN;
5481 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 }
William Lallemand723b73a2012-02-08 16:37:49 +01005483
William Lallemand0f99e342011-10-12 17:50:54 +02005484 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5485 /* delete previous herited or defined syslog servers */
5486 struct logsrv *back;
5487
5488 if (*(args[1]) != 0) {
5489 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
5492 }
5493
William Lallemand723b73a2012-02-08 16:37:49 +01005494 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5495 LIST_DEL(&tmplogsrv->list);
5496 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005497 }
5498 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005500 struct logsrv *logsrv;
5501
Willy Tarreaubaaee002006-06-26 02:48:02 +02005502 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005503 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005504 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005505 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005506 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005507 LIST_INIT(&node->list);
5508 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
5511 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005512 struct sockaddr_storage *sk;
5513 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005514
5515 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005516
William Lallemand0f99e342011-10-12 17:50:54 +02005517 logsrv->facility = get_log_facility(args[2]);
5518 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005519 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
5522
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
5524
William Lallemand0f99e342011-10-12 17:50:54 +02005525 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005526 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005527 logsrv->level = get_log_level(args[3]);
5528 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005529 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005530 err_code |= ERR_ALERT | ERR_FATAL;
5531 goto out;
5532
Willy Tarreaubaaee002006-06-26 02:48:02 +02005533 }
5534 }
5535
William Lallemand0f99e342011-10-12 17:50:54 +02005536 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005537 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005538 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005539 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005540 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005544 }
5545 }
5546
Willy Tarreau902636f2013-03-10 19:44:48 +01005547 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005548 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005549 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005550 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005551 goto out;
5552 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005553
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005554 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005555
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005556 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005557 if (port1 != port2) {
5558 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5559 file, linenum, args[0], args[1]);
5560 err_code |= ERR_ALERT | ERR_FATAL;
5561 goto out;
5562 }
5563
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005564 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005565 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005566 }
William Lallemand0f99e342011-10-12 17:50:54 +02005567
5568 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 }
5570 else {
5571 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5572 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005575 }
5576 }
5577 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005578 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005579 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005580 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005581 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005582
Willy Tarreau977b8e42006-12-29 14:19:17 +01005583 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005585
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005587 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5588 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005592
5593 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005594 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5595 free(curproxy->conn_src.iface_name);
5596 curproxy->conn_src.iface_name = NULL;
5597 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005598
Willy Tarreau902636f2013-03-10 19:44:48 +01005599 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005600 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005601 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005602 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005603 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005604 goto out;
5605 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005606
5607 proto = protocol_by_family(sk->ss_family);
5608 if (!proto || !proto->connect) {
5609 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005610 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005614
5615 if (port1 != port2) {
5616 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5617 file, linenum, args[0], args[1]);
5618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
5621
Willy Tarreauef9a3602012-12-08 22:29:20 +01005622 curproxy->conn_src.source_addr = *sk;
5623 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005624
5625 cur_arg = 2;
5626 while (*(args[cur_arg])) {
5627 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005628#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5629#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005630 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005631 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5632 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005633 err_code |= ERR_ALERT | ERR_FATAL;
5634 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005635 }
5636#endif
5637 if (!*args[cur_arg + 1]) {
5638 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5639 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005640 err_code |= ERR_ALERT | ERR_FATAL;
5641 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005642 }
5643
5644 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005645 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5646 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005647 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005648 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5649 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005650 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5651 char *name, *end;
5652
5653 name = args[cur_arg+1] + 7;
5654 while (isspace(*name))
5655 name++;
5656
5657 end = name;
5658 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5659 end++;
5660
Willy Tarreauef9a3602012-12-08 22:29:20 +01005661 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5662 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5663 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5664 curproxy->conn_src.bind_hdr_len = end - name;
5665 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5666 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5667 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005668
5669 /* now look for an occurrence number */
5670 while (isspace(*end))
5671 end++;
5672 if (*end == ',') {
5673 end++;
5674 name = end;
5675 if (*end == '-')
5676 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005677 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005678 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005679 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005680 }
5681
Willy Tarreauef9a3602012-12-08 22:29:20 +01005682 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005683 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5684 " occurrences values smaller than %d.\n",
5685 file, linenum, MAX_HDR_HISTORY);
5686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
5688 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005689 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005690 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005691
Willy Tarreau902636f2013-03-10 19:44:48 +01005692 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005693 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005694 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005695 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005696 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005697 goto out;
5698 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005699
5700 proto = protocol_by_family(sk->ss_family);
5701 if (!proto || !proto->connect) {
5702 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5703 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005704 err_code |= ERR_ALERT | ERR_FATAL;
5705 goto out;
5706 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005707
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005708 if (port1 != port2) {
5709 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5710 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005711 err_code |= ERR_ALERT | ERR_FATAL;
5712 goto out;
5713 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005714 curproxy->conn_src.tproxy_addr = *sk;
5715 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005716 }
5717 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005718#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005719 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005720#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005721#else /* no TPROXY support */
5722 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005723 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005726#endif
5727 cur_arg += 2;
5728 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005729 }
5730
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005731 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5732#ifdef SO_BINDTODEVICE
5733 if (!*args[cur_arg + 1]) {
5734 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5735 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005738 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005739 free(curproxy->conn_src.iface_name);
5740 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5741 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005742 global.last_checks |= LSTCHK_NETADM;
5743#else
5744 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5745 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005748#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005749 cur_arg += 2;
5750 continue;
5751 }
5752 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005753 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
5755 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005757 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005758 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5759 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5760 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_ALERT | ERR_FATAL;
5762 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005763 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005765 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005766 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5767 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005770 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005771
5772 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005773 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005774 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005775 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005776 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005777 }
5778 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005779 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005780 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005781 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005782 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005784 }
5785 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005786 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005787 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005788 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005789 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005790 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
5792 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005793 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005794 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005795 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005796 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 }
5799 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005800 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005801 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005802 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005803 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005804 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005805 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005806 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005807 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005808 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005809 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005810 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005811 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005812 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005813 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005814 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005815 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005816 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005817 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005818 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005819 }
5820 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005821 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005822 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005823 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005824 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005825 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005828 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005829 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5830 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005831 err_code |= ERR_ALERT | ERR_FATAL;
5832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005834
5835 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005836 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005837 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005838 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005840 }
5841 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005842 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005843 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005844 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005845 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 }
5848 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005849 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005850 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005851 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005852 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005854 }
5855 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005856 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005857 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005858 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005859 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005860 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861 }
5862 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005863 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005864 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005865 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005866 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005867 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005868 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005869 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005870 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005871 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005872 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005873 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005874 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005876 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005877 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005878
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879 if (curproxy == &defproxy) {
5880 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005884 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005885 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 if (*(args[1]) == 0) {
5888 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005889 err_code |= ERR_ALERT | ERR_FATAL;
5890 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005892
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005893 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005894 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5895 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5896 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005900 err_code |= warnif_cond_conflicts(cond,
5901 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5902 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005903 }
5904 else if (*args[2]) {
5905 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5906 file, linenum, args[0], args[2]);
5907 err_code |= ERR_ALERT | ERR_FATAL;
5908 goto out;
5909 }
5910
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005911 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005912 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005913 wl->s = strdup(args[1]);
5914 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005915 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 }
5917 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005918 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005921 err_code |= ERR_ALERT | ERR_FATAL;
5922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005924
Willy Tarreauade5ec42010-01-28 19:33:49 +01005925 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005926 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005927 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005928 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 }
5931 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005932 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005933 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005934 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005935 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005936 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005937 }
5938 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005939 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005940 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005941 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005942 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005943 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 }
5945 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005946 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005947 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005949 err_code |= ERR_ALERT | ERR_FATAL;
5950 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005951 }
5952
Willy Tarreauade5ec42010-01-28 19:33:49 +01005953 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005954 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005955 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005956 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005957 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 }
5959 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005960 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005961 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005962 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005963 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005965 }
5966 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005967 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005968 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005969 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005970 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005972 }
5973 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005974 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005975
Willy Tarreaubaaee002006-06-26 02:48:02 +02005976 if (curproxy == &defproxy) {
5977 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005978 err_code |= ERR_ALERT | ERR_FATAL;
5979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005981 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005982 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005983
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 if (*(args[1]) == 0) {
5985 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005986 err_code |= ERR_ALERT | ERR_FATAL;
5987 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005988 }
5989
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005990 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005991 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5992 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5993 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005994 err_code |= ERR_ALERT | ERR_FATAL;
5995 goto out;
5996 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005997 err_code |= warnif_cond_conflicts(cond,
5998 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5999 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006000 }
6001 else if (*args[2]) {
6002 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6003 file, linenum, args[0], args[2]);
6004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
6006 }
6007
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006008 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006009 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006010 wl->s = strdup(args[1]);
6011 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 }
6013 else if (!strcmp(args[0], "errorloc") ||
6014 !strcmp(args[0], "errorloc302") ||
6015 !strcmp(args[0], "errorloc303")) { /* error location */
6016 int errnum, errlen;
6017 char *err;
6018
Willy Tarreau977b8e42006-12-29 14:19:17 +01006019 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006020 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006021
Willy Tarreaubaaee002006-06-26 02:48:02 +02006022 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006023 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 }
6027
6028 errnum = atol(args[1]);
6029 if (!strcmp(args[0], "errorloc303")) {
6030 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
6031 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
6032 } else {
6033 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
6034 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
6035 }
6036
Willy Tarreau0f772532006-12-23 20:51:41 +01006037 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6038 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006039 chunk_destroy(&curproxy->errmsg[rc]);
6040 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006041 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006044
6045 if (rc >= HTTP_ERR_SIZE) {
6046 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6047 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 free(err);
6049 }
6050 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006051 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6052 int errnum, errlen, fd;
6053 char *err;
6054 struct stat stat;
6055
6056 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006057 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006058
6059 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006060 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006061 err_code |= ERR_ALERT | ERR_FATAL;
6062 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006063 }
6064
6065 fd = open(args[2], O_RDONLY);
6066 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6067 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6068 file, linenum, args[2], args[1]);
6069 if (fd >= 0)
6070 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006071 err_code |= ERR_ALERT | ERR_FATAL;
6072 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006073 }
6074
Willy Tarreau27a674e2009-08-17 07:23:33 +02006075 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006076 errlen = stat.st_size;
6077 } else {
6078 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006079 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006080 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006081 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006082 }
6083
6084 err = malloc(errlen); /* malloc() must succeed during parsing */
6085 errnum = read(fd, err, errlen);
6086 if (errnum != errlen) {
6087 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6088 file, linenum, args[2], args[1]);
6089 close(fd);
6090 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006091 err_code |= ERR_ALERT | ERR_FATAL;
6092 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006093 }
6094 close(fd);
6095
6096 errnum = atol(args[1]);
6097 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6098 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006099 chunk_destroy(&curproxy->errmsg[rc]);
6100 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006101 break;
6102 }
6103 }
6104
6105 if (rc >= HTTP_ERR_SIZE) {
6106 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6107 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006108 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006109 free(err);
6110 }
6111 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006112 else if (!strcmp(args[0], "compression")) {
6113 struct comp *comp;
6114 if (curproxy->comp == NULL) {
6115 comp = calloc(1, sizeof(struct comp));
6116 curproxy->comp = comp;
6117 } else {
6118 comp = curproxy->comp;
6119 }
6120
6121 if (!strcmp(args[1], "algo")) {
6122 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006123 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006124
William Lallemand82fe75c2012-10-23 10:25:10 +02006125 cur_arg = 2;
6126 if (!*args[cur_arg]) {
6127 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6128 file, linenum, args[0]);
6129 err_code |= ERR_ALERT | ERR_FATAL;
6130 goto out;
6131 }
6132 while (*(args[cur_arg])) {
6133 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6134 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6135 file, linenum, args[0], args[cur_arg]);
6136 err_code |= ERR_ALERT | ERR_FATAL;
6137 goto out;
6138 }
William Lallemand552df672012-11-07 13:21:47 +01006139 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6140 curproxy->comp->algos->end(&ctx);
6141 } else {
6142 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6143 file, linenum, args[0], args[cur_arg]);
6144 err_code |= ERR_ALERT | ERR_FATAL;
6145 goto out;
6146 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006147 cur_arg ++;
6148 continue;
6149 }
6150 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006151 else if (!strcmp(args[1], "offload")) {
6152 comp->offload = 1;
6153 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006154 else if (!strcmp(args[1], "type")) {
6155 int cur_arg;
6156 cur_arg = 2;
6157 if (!*args[cur_arg]) {
6158 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6159 file, linenum, args[0]);
6160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
6162 }
6163 while (*(args[cur_arg])) {
6164 comp_append_type(comp, args[cur_arg]);
6165 cur_arg ++;
6166 continue;
6167 }
6168 }
6169 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006170 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006171 file, linenum, args[0]);
6172 err_code |= ERR_ALERT | ERR_FATAL;
6173 goto out;
6174 }
6175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006177 struct cfg_kw_list *kwl;
6178 int index;
6179
6180 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6181 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6182 if (kwl->kw[index].section != CFG_LISTEN)
6183 continue;
6184 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6185 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006186 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006187 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006188 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006189 err_code |= ERR_ALERT | ERR_FATAL;
6190 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006191 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006192 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006193 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006194 err_code |= ERR_WARN;
6195 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006196 }
Willy Tarreau93893792009-07-23 13:19:11 +02006197 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006198 }
6199 }
6200 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006201
Willy Tarreau6daf3432008-01-22 16:44:08 +01006202 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006203 err_code |= ERR_ALERT | ERR_FATAL;
6204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 }
Willy Tarreau93893792009-07-23 13:19:11 +02006206 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006207 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006208 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209}
6210
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006211int
6212cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6213{
6214
6215 int err_code = 0;
6216 const char *err;
6217
6218 if (!strcmp(args[0], "userlist")) { /* new userlist */
6219 struct userlist *newul;
6220
6221 if (!*args[1]) {
6222 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6223 file, linenum, args[0]);
6224 err_code |= ERR_ALERT | ERR_FATAL;
6225 goto out;
6226 }
6227
6228 err = invalid_char(args[1]);
6229 if (err) {
6230 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6231 file, linenum, *err, args[0], args[1]);
6232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234 }
6235
6236 for (newul = userlist; newul; newul = newul->next)
6237 if (!strcmp(newul->name, args[1])) {
6238 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6239 file, linenum, args[1]);
6240 err_code |= ERR_WARN;
6241 goto out;
6242 }
6243
6244 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6245 if (!newul) {
6246 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6247 err_code |= ERR_ALERT | ERR_ABORT;
6248 goto out;
6249 }
6250
6251 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6252 newul->name = strdup(args[1]);
6253
6254 if (!newul->groupusers | !newul->name) {
6255 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6256 err_code |= ERR_ALERT | ERR_ABORT;
6257 goto out;
6258 }
6259
6260 newul->next = userlist;
6261 userlist = newul;
6262
6263 } else if (!strcmp(args[0], "group")) { /* new group */
6264 int cur_arg, i;
6265 const char *err;
6266
6267 if (!*args[1]) {
6268 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6269 file, linenum, args[0]);
6270 err_code |= ERR_ALERT | ERR_FATAL;
6271 goto out;
6272 }
6273
6274 err = invalid_char(args[1]);
6275 if (err) {
6276 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6277 file, linenum, *err, args[0], args[1]);
6278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
6280 }
6281
6282 for(i = 0; i < userlist->grpcnt; i++)
6283 if (!strcmp(userlist->groups[i], args[1])) {
6284 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6285 file, linenum, args[1], userlist->name);
6286 err_code |= ERR_ALERT;
6287 goto out;
6288 }
6289
6290 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6291 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6292 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6293 err_code |= ERR_ALERT | ERR_FATAL;
6294 goto out;
6295 }
6296
6297 cur_arg = 2;
6298
6299 while (*args[cur_arg]) {
6300 if (!strcmp(args[cur_arg], "users")) {
6301 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6302 cur_arg += 2;
6303 continue;
6304 } else {
6305 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6306 file, linenum, args[0]);
6307 err_code |= ERR_ALERT | ERR_FATAL;
6308 goto out;
6309 }
6310 }
6311
6312 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6313 } else if (!strcmp(args[0], "user")) { /* new user */
6314 struct auth_users *newuser;
6315 int cur_arg;
6316
6317 if (!*args[1]) {
6318 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6319 file, linenum, args[0]);
6320 err_code |= ERR_ALERT | ERR_FATAL;
6321 goto out;
6322 }
6323
6324 for (newuser = userlist->users; newuser; newuser = newuser->next)
6325 if (!strcmp(newuser->user, args[1])) {
6326 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6327 file, linenum, args[1], userlist->name);
6328 err_code |= ERR_ALERT;
6329 goto out;
6330 }
6331
6332 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6333 if (!newuser) {
6334 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6335 err_code |= ERR_ALERT | ERR_ABORT;
6336 goto out;
6337 }
6338
6339 newuser->user = strdup(args[1]);
6340
6341 newuser->next = userlist->users;
6342 userlist->users = newuser;
6343
6344 cur_arg = 2;
6345
6346 while (*args[cur_arg]) {
6347 if (!strcmp(args[cur_arg], "password")) {
6348#ifndef CONFIG_HAP_CRYPT
6349 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6350 file, linenum);
6351 err_code |= ERR_ALERT;
6352#endif
6353 newuser->pass = strdup(args[cur_arg + 1]);
6354 cur_arg += 2;
6355 continue;
6356 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6357 newuser->pass = strdup(args[cur_arg + 1]);
6358 newuser->flags |= AU_O_INSECURE;
6359 cur_arg += 2;
6360 continue;
6361 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006362 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006363 cur_arg += 2;
6364 continue;
6365 } else {
6366 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6367 file, linenum, args[0]);
6368 err_code |= ERR_ALERT | ERR_FATAL;
6369 goto out;
6370 }
6371 }
6372 } else {
6373 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6374 err_code |= ERR_ALERT | ERR_FATAL;
6375 }
6376
6377out:
6378 return err_code;
6379}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380
6381/*
6382 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006383 * Returns the error code, 0 if OK, or any combination of :
6384 * - ERR_ABORT: must abort ASAP
6385 * - ERR_FATAL: we can continue parsing but not start the service
6386 * - ERR_WARN: a warning has been emitted
6387 * - ERR_ALERT: an alert has been emitted
6388 * Only the two first ones can stop processing, the two others are just
6389 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006390 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006391int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006393 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006394 FILE *f;
6395 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006396 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006397 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006398
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 if ((f=fopen(file,"r")) == NULL)
6400 return -1;
6401
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006402 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006403 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006404 char *end;
6405 char *args[MAX_LINE_ARGS + 1];
6406 char *line = thisline;
6407
Willy Tarreaubaaee002006-06-26 02:48:02 +02006408 linenum++;
6409
6410 end = line + strlen(line);
6411
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006412 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6413 /* Check if we reached the limit and the last char is not \n.
6414 * Watch out for the last line without the terminating '\n'!
6415 */
6416 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006417 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006418 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006419 }
6420
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006422 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423 line++;
6424
6425 arg = 0;
6426 args[arg] = line;
6427
6428 while (*line && arg < MAX_LINE_ARGS) {
6429 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6430 * C equivalent value. Other combinations left unchanged (eg: \1).
6431 */
6432 if (*line == '\\') {
6433 int skip = 0;
6434 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6435 *line = line[1];
6436 skip = 1;
6437 }
6438 else if (line[1] == 'r') {
6439 *line = '\r';
6440 skip = 1;
6441 }
6442 else if (line[1] == 'n') {
6443 *line = '\n';
6444 skip = 1;
6445 }
6446 else if (line[1] == 't') {
6447 *line = '\t';
6448 skip = 1;
6449 }
6450 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006451 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006452 unsigned char hex1, hex2;
6453 hex1 = toupper(line[2]) - '0';
6454 hex2 = toupper(line[3]) - '0';
6455 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6456 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6457 *line = (hex1<<4) + hex2;
6458 skip = 3;
6459 }
6460 else {
6461 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006462 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006463 }
6464 }
6465 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006466 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006467 end -= skip;
6468 }
6469 line++;
6470 }
6471 else if (*line == '#' || *line == '\n' || *line == '\r') {
6472 /* end of string, end of loop */
6473 *line = 0;
6474 break;
6475 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006476 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006478 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006479 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480 line++;
6481 args[++arg] = line;
6482 }
6483 else {
6484 line++;
6485 }
6486 }
6487
6488 /* empty line */
6489 if (!**args)
6490 continue;
6491
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006492 if (*line) {
6493 /* we had to stop due to too many args.
6494 * Let's terminate the string, print the offending part then cut the
6495 * last arg.
6496 */
6497 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6498 line++;
6499 *line = '\0';
6500
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006501 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006502 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006503 err_code |= ERR_ALERT | ERR_FATAL;
6504 args[arg] = line;
6505 }
6506
Willy Tarreau540abe42007-05-02 20:50:16 +02006507 /* zero out remaining args and ensure that at least one entry
6508 * is zeroed out.
6509 */
6510 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006511 args[arg] = line;
6512 }
6513
Willy Tarreau3842f002009-06-14 11:39:52 +02006514 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006515 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006516 char *tmp;
6517
Willy Tarreau3842f002009-06-14 11:39:52 +02006518 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006519 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006520 for (arg=0; *args[arg+1]; arg++)
6521 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006522 *tmp = '\0'; // fix the next arg to \0
6523 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006524 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006525 else if (!strcmp(args[0], "default")) {
6526 kwm = KWM_DEF;
6527 for (arg=0; *args[arg+1]; arg++)
6528 args[arg] = args[arg+1]; // shift args after inversion
6529 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006530
William Lallemand0f99e342011-10-12 17:50:54 +02006531 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6532 strcmp(args[0], "log") != 0) {
6533 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006534 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006535 }
6536
Willy Tarreau977b8e42006-12-29 14:19:17 +01006537 if (!strcmp(args[0], "listen") ||
6538 !strcmp(args[0], "frontend") ||
6539 !strcmp(args[0], "backend") ||
6540 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006541 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006543 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006544 cursection = strdup(args[0]);
6545 }
6546 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006548 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006549 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006550 }
6551 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006552 confsect = CFG_USERLIST;
6553 free(cursection);
6554 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006555 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006556 else if (!strcmp(args[0], "peers")) {
6557 confsect = CFG_PEERS;
6558 free(cursection);
6559 cursection = strdup(args[0]);
6560 }
6561
Willy Tarreaubaaee002006-06-26 02:48:02 +02006562 /* else it's a section keyword */
6563
6564 switch (confsect) {
6565 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006566 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006567 break;
6568 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006569 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006570 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006571 case CFG_USERLIST:
6572 err_code |= cfg_parse_users(file, linenum, args, kwm);
6573 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006574 case CFG_PEERS:
6575 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6576 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006577 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006578 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006579 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006580 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006581
6582 if (err_code & ERR_ABORT)
6583 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006585 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006586 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006587 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006588 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006589}
6590
Willy Tarreaubb925012009-07-23 13:36:36 +02006591/*
6592 * Returns the error code, 0 if OK, or any combination of :
6593 * - ERR_ABORT: must abort ASAP
6594 * - ERR_FATAL: we can continue parsing but not start the service
6595 * - ERR_WARN: a warning has been emitted
6596 * - ERR_ALERT: an alert has been emitted
6597 * Only the two first ones can stop processing, the two others are just
6598 * indicators.
6599 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006600int check_config_validity()
6601{
6602 int cfgerr = 0;
6603 struct proxy *curproxy = NULL;
6604 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006605 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006606 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006607 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006608 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006610 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 /*
6612 * Now, check for the integrity of all that we have collected.
6613 */
6614
6615 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006616 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006617
Willy Tarreau193b8c62012-11-22 00:17:38 +01006618 if (!global.tune.max_http_hdr)
6619 global.tune.max_http_hdr = MAX_HTTP_HDR;
6620
6621 if (!global.tune.cookie_len)
6622 global.tune.cookie_len = CAPTURE_LEN;
6623
6624 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6625
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006626 /* first, we will invert the proxy list order */
6627 curproxy = NULL;
6628 while (proxy) {
6629 struct proxy *next;
6630
6631 next = proxy->next;
6632 proxy->next = curproxy;
6633 curproxy = proxy;
6634 if (!next)
6635 break;
6636 proxy = next;
6637 }
6638
Willy Tarreaubaaee002006-06-26 02:48:02 +02006639 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006640 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006641 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006642 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006643 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006644 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006645 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006646 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006647
Willy Tarreau050536d2012-10-04 08:47:34 +02006648 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006649 /* proxy ID not set, use automatic numbering with first
6650 * spare entry starting with next_pxid.
6651 */
6652 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6653 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6654 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006655 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006656 next_pxid++;
6657
Willy Tarreau55ea7572007-06-17 19:56:27 +02006658
Willy Tarreaubaaee002006-06-26 02:48:02 +02006659 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006660 /* ensure we don't keep listeners uselessly bound */
6661 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006662 curproxy = curproxy->next;
6663 continue;
6664 }
6665
Willy Tarreau16a21472012-11-19 12:39:59 +01006666 /* number of processes this proxy is bound to */
6667 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6668
Willy Tarreauff01a212009-03-15 13:46:16 +01006669 switch (curproxy->mode) {
6670 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006671 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006672 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006673 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6674 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006675 cfgerr++;
6676 }
6677
6678 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006679 Warning("config : servers will be ignored for %s '%s'.\n",
6680 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006681 break;
6682
6683 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006684 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006685 break;
6686
6687 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006688 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006689 break;
6690 }
6691
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006692 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006693 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006694 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006695 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6696 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006697 cfgerr++;
6698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006699#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006700 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006701 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6702 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006703 cfgerr++;
6704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006705#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006706 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006707 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6708 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006709 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006710 }
6711 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006712 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006713 /* If no LB algo is set in a backend, and we're not in
6714 * transparent mode, dispatch mode nor proxy mode, we
6715 * want to use balance roundrobin by default.
6716 */
6717 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6718 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006719 }
6720 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006721
Willy Tarreau1620ec32011-08-06 17:05:02 +02006722 if (curproxy->options & PR_O_DISPATCH)
6723 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6724 else if (curproxy->options & PR_O_HTTP_PROXY)
6725 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6726 else if (curproxy->options & PR_O_TRANSP)
6727 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006728
Willy Tarreau1620ec32011-08-06 17:05:02 +02006729 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6730 if (curproxy->options & PR_O_DISABLE404) {
6731 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6732 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6733 err_code |= ERR_WARN;
6734 curproxy->options &= ~PR_O_DISABLE404;
6735 }
6736 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6737 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6738 "send-state", proxy_type_str(curproxy), curproxy->id);
6739 err_code |= ERR_WARN;
6740 curproxy->options &= ~PR_O2_CHK_SNDST;
6741 }
Willy Tarreauef781042010-01-27 11:53:01 +01006742 }
6743
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006744 /* if a default backend was specified, let's find it */
6745 if (curproxy->defbe.name) {
6746 struct proxy *target;
6747
Alex Williams96532db2009-11-01 21:27:13 -05006748 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006749 if (!target) {
6750 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6751 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006752 cfgerr++;
6753 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006754 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6755 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006756 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006757 } else {
6758 free(curproxy->defbe.name);
6759 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006760 /* we force the backend to be present on at least all of
6761 * the frontend's processes.
6762 */
6763 target->bind_proc = curproxy->bind_proc ?
6764 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006765
6766 /* Emit a warning if this proxy also has some servers */
6767 if (curproxy->srv) {
6768 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6769 curproxy->id);
6770 err_code |= ERR_WARN;
6771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006772 }
6773 }
6774
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006775 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006776 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6777 /* map jump target for ACT_SETBE in req_rep chain */
6778 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006779 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006780 struct proxy *target;
6781
Willy Tarreaua496b602006-12-17 23:15:24 +01006782 if (exp->action != ACT_SETBE)
6783 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006784
Alex Williams96532db2009-11-01 21:27:13 -05006785 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006786 if (!target) {
6787 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6788 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006789 cfgerr++;
6790 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006791 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6792 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006793 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006794 } else {
6795 free((void *)exp->replace);
6796 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006797 /* we force the backend to be present on at least all of
6798 * the frontend's processes.
6799 */
6800 target->bind_proc = curproxy->bind_proc ?
6801 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006802 }
6803 }
6804 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006805
6806 /* find the target proxy for 'use_backend' rules */
6807 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006808 struct proxy *target;
6809
Alex Williams96532db2009-11-01 21:27:13 -05006810 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006811
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006812 if (!target) {
6813 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6814 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006815 cfgerr++;
6816 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006817 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6818 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006819 cfgerr++;
6820 } else {
6821 free((void *)rule->be.name);
6822 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006823 /* we force the backend to be present on at least all of
6824 * the frontend's processes.
6825 */
6826 target->bind_proc = curproxy->bind_proc ?
6827 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006828 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006829 }
6830
6831 /* find the target proxy for 'use_backend' rules */
6832 list_for_each_entry(srule, &curproxy->server_rules, list) {
6833 struct server *target = findserver(curproxy, srule->srv.name);
6834
6835 if (!target) {
6836 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6837 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6838 cfgerr++;
6839 continue;
6840 }
6841 free((void *)srule->srv.name);
6842 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006843 }
6844
Emeric Brunb982a3d2010-01-04 15:45:53 +01006845 /* find the target table for 'stick' rules */
6846 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6847 struct proxy *target;
6848
Emeric Brun1d33b292010-01-04 15:47:17 +01006849 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6850 if (mrule->flags & STK_IS_STORE)
6851 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6852
Emeric Brunb982a3d2010-01-04 15:45:53 +01006853 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006854 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006855 else
6856 target = curproxy;
6857
6858 if (!target) {
6859 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6860 curproxy->id, mrule->table.name);
6861 cfgerr++;
6862 }
6863 else if (target->table.size == 0) {
6864 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6865 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6866 cfgerr++;
6867 }
Willy Tarreau12785782012-04-27 21:37:17 +02006868 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6869 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006870 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6871 cfgerr++;
6872 }
6873 else {
6874 free((void *)mrule->table.name);
6875 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006876 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006877 }
6878 }
6879
6880 /* find the target table for 'store response' rules */
6881 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6882 struct proxy *target;
6883
Emeric Brun1d33b292010-01-04 15:47:17 +01006884 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6885
Emeric Brunb982a3d2010-01-04 15:45:53 +01006886 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006887 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006888 else
6889 target = curproxy;
6890
6891 if (!target) {
6892 Alert("Proxy '%s': unable to find store table '%s'.\n",
6893 curproxy->id, mrule->table.name);
6894 cfgerr++;
6895 }
6896 else if (target->table.size == 0) {
6897 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6898 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6899 cfgerr++;
6900 }
Willy Tarreau12785782012-04-27 21:37:17 +02006901 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6902 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006903 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6904 cfgerr++;
6905 }
6906 else {
6907 free((void *)mrule->table.name);
6908 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006909 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006910 }
6911 }
6912
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006913 /* find the target table for 'tcp-request' layer 4 rules */
6914 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6915 struct proxy *target;
6916
Willy Tarreaub4c84932013-07-23 19:15:30 +02006917 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006918 continue;
6919
6920 if (trule->act_prm.trk_ctr.table.n)
6921 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6922 else
6923 target = curproxy;
6924
6925 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006926 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6927 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006928 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006929 cfgerr++;
6930 }
6931 else if (target->table.size == 0) {
6932 Alert("Proxy '%s': table '%s' used but not configured.\n",
6933 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6934 cfgerr++;
6935 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006936 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6937 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6938 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 +01006939 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006940 cfgerr++;
6941 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006942 else {
6943 free(trule->act_prm.trk_ctr.table.n);
6944 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006945 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006946 * to pass a list of counters to track and allocate them right here using
6947 * stktable_alloc_data_type().
6948 */
6949 }
6950 }
6951
Willy Tarreaud1f96522010-08-03 19:34:32 +02006952 /* find the target table for 'tcp-request' layer 6 rules */
6953 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6954 struct proxy *target;
6955
Willy Tarreaub4c84932013-07-23 19:15:30 +02006956 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006957 continue;
6958
6959 if (trule->act_prm.trk_ctr.table.n)
6960 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6961 else
6962 target = curproxy;
6963
6964 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006965 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6966 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006967 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006968 cfgerr++;
6969 }
6970 else if (target->table.size == 0) {
6971 Alert("Proxy '%s': table '%s' used but not configured.\n",
6972 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6973 cfgerr++;
6974 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006975 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6976 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6977 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 +01006978 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006979 cfgerr++;
6980 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006981 else {
6982 free(trule->act_prm.trk_ctr.table.n);
6983 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006984 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006985 * to pass a list of counters to track and allocate them right here using
6986 * stktable_alloc_data_type().
6987 */
6988 }
6989 }
6990
Emeric Brun32da3c42010-09-23 18:39:19 +02006991 if (curproxy->table.peers.name) {
6992 struct peers *curpeers = peers;
6993
6994 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6995 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6996 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006997 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006998 break;
6999 }
7000 }
7001
7002 if (!curpeers) {
7003 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7004 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007005 free((void *)curproxy->table.peers.name);
7006 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007007 cfgerr++;
7008 }
7009 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007010 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7011 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007012 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007013 cfgerr++;
7014 }
7015 }
7016
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007017 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007018 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007019 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7020 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7021 "proxy", curproxy->id);
7022 cfgerr++;
7023 goto out_uri_auth_compat;
7024 }
7025
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007026 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007027 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007028 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007029 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007030
Willy Tarreau95fa4692010-02-01 13:05:50 +01007031 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7032 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007033
7034 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007035 uri_auth_compat_req[i++] = "realm";
7036 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7037 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007038
Willy Tarreau95fa4692010-02-01 13:05:50 +01007039 uri_auth_compat_req[i++] = "unless";
7040 uri_auth_compat_req[i++] = "{";
7041 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7042 uri_auth_compat_req[i++] = "}";
7043 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007044
Willy Tarreauff011f22011-01-06 17:51:27 +01007045 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7046 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007047 cfgerr++;
7048 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007049 }
7050
Willy Tarreauff011f22011-01-06 17:51:27 +01007051 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007052
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007053 if (curproxy->uri_auth->auth_realm) {
7054 free(curproxy->uri_auth->auth_realm);
7055 curproxy->uri_auth->auth_realm = NULL;
7056 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007057
7058 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007059 }
7060out_uri_auth_compat:
7061
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007062 /* compile the log format */
7063 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007064 if (curproxy->conf.logformat_string != default_http_log_format &&
7065 curproxy->conf.logformat_string != default_tcp_log_format &&
7066 curproxy->conf.logformat_string != clf_http_log_format)
7067 free(curproxy->conf.logformat_string);
7068 curproxy->conf.logformat_string = NULL;
7069 free(curproxy->conf.lfs_file);
7070 curproxy->conf.lfs_file = NULL;
7071 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007072 }
7073
Willy Tarreau62a61232013-04-12 18:13:46 +02007074 if (curproxy->conf.logformat_string) {
7075 curproxy->conf.args.ctx = ARGC_LOG;
7076 curproxy->conf.args.file = curproxy->conf.lfs_file;
7077 curproxy->conf.args.line = curproxy->conf.lfs_line;
7078 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007079 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02007080 curproxy->conf.args.file = NULL;
7081 curproxy->conf.args.line = 0;
7082 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007083
Willy Tarreau62a61232013-04-12 18:13:46 +02007084 if (curproxy->conf.uniqueid_format_string) {
7085 curproxy->conf.args.ctx = ARGC_UIF;
7086 curproxy->conf.args.file = curproxy->conf.uif_file;
7087 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007088 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007089 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02007090 curproxy->conf.args.file = NULL;
7091 curproxy->conf.args.line = 0;
7092 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007093
7094 /* only now we can check if some args remain unresolved */
7095 cfgerr += smp_resolve_args(curproxy);
7096 if (!cfgerr)
7097 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007098
Willy Tarreau2738a142006-07-08 17:28:09 +02007099 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007100 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007101 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007102 (!curproxy->timeout.connect ||
7103 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007104 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007105 " | While not properly invalid, you will certainly encounter various problems\n"
7106 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007107 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007108 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007109 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007110 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007111
Willy Tarreau1fa31262007-12-03 00:36:16 +01007112 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7113 * We must still support older configurations, so let's find out whether those
7114 * parameters have been set or must be copied from contimeouts.
7115 */
7116 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007117 if (!curproxy->timeout.tarpit ||
7118 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007119 /* tarpit timeout not set. We search in the following order:
7120 * default.tarpit, curr.connect, default.connect.
7121 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007122 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007123 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007124 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007125 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007126 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007127 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007128 }
7129 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007130 (!curproxy->timeout.queue ||
7131 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007132 /* queue timeout not set. We search in the following order:
7133 * default.queue, curr.connect, default.connect.
7134 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007135 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007136 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007137 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007138 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007139 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007140 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007141 }
7142 }
7143
Willy Tarreau1620ec32011-08-06 17:05:02 +02007144 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007145 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7146 curproxy->check_req = (char *)malloc(curproxy->check_len);
7147 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007148 }
7149
Willy Tarreau193b8c62012-11-22 00:17:38 +01007150 /* ensure that cookie capture length is not too large */
7151 if (curproxy->capture_len >= global.tune.cookie_len) {
7152 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7153 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7154 err_code |= ERR_WARN;
7155 curproxy->capture_len = global.tune.cookie_len - 1;
7156 }
7157
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007158 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007159 if (curproxy->nb_req_cap) {
7160 if (curproxy->mode == PR_MODE_HTTP) {
7161 curproxy->req_cap_pool = create_pool("ptrcap",
7162 curproxy->nb_req_cap * sizeof(char *),
7163 MEM_F_SHARED);
7164 } else {
7165 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7166 proxy_type_str(curproxy), curproxy->id);
7167 err_code |= ERR_WARN;
7168 curproxy->to_log &= ~LW_REQHDR;
7169 curproxy->nb_req_cap = 0;
7170 }
7171 }
7172
7173 if (curproxy->nb_rsp_cap) {
7174 if (curproxy->mode == PR_MODE_HTTP) {
7175 curproxy->rsp_cap_pool = create_pool("ptrcap",
7176 curproxy->nb_rsp_cap * sizeof(char *),
7177 MEM_F_SHARED);
7178 } else {
7179 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7180 proxy_type_str(curproxy), curproxy->id);
7181 err_code |= ERR_WARN;
7182 curproxy->to_log &= ~LW_REQHDR;
7183 curproxy->nb_rsp_cap = 0;
7184 }
7185 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007186
Willy Tarreaubaaee002006-06-26 02:48:02 +02007187 /* first, we will invert the servers list order */
7188 newsrv = NULL;
7189 while (curproxy->srv) {
7190 struct server *next;
7191
7192 next = curproxy->srv->next;
7193 curproxy->srv->next = newsrv;
7194 newsrv = curproxy->srv;
7195 if (!next)
7196 break;
7197 curproxy->srv = next;
7198 }
7199
Willy Tarreau17edc812014-01-03 12:14:34 +01007200 /* Check that no server name conflicts. This causes trouble in the stats.
7201 * We only emit a warning for the first conflict affecting each server,
7202 * in order to avoid combinatory explosion if all servers have the same
7203 * name. We do that only for servers which do not have an explicit ID,
7204 * because these IDs were made also for distinguishing them and we don't
7205 * want to annoy people who correctly manage them.
7206 */
7207 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7208 struct server *other_srv;
7209
7210 if (newsrv->puid)
7211 continue;
7212
7213 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7214 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7215 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7216 newsrv->conf.file, newsrv->conf.line,
7217 proxy_type_str(curproxy), curproxy->id,
7218 newsrv->id, other_srv->conf.line);
7219 break;
7220 }
7221 }
7222 }
7223
Willy Tarreaudd701652010-05-25 23:03:02 +02007224 /* assign automatic UIDs to servers which don't have one yet */
7225 next_id = 1;
7226 newsrv = curproxy->srv;
7227 while (newsrv != NULL) {
7228 if (!newsrv->puid) {
7229 /* server ID not set, use automatic numbering with first
7230 * spare entry starting with next_svid.
7231 */
7232 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7233 newsrv->conf.id.key = newsrv->puid = next_id;
7234 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7235 }
7236 next_id++;
7237 newsrv = newsrv->next;
7238 }
7239
Willy Tarreau20697042007-11-15 23:26:18 +01007240 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007241 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007242
Willy Tarreau62c3be22012-01-20 13:12:32 +01007243 /*
7244 * If this server supports a maxconn parameter, it needs a dedicated
7245 * tasks to fill the emptied slots when a connection leaves.
7246 * Also, resolve deferred tracking dependency if needed.
7247 */
7248 newsrv = curproxy->srv;
7249 while (newsrv != NULL) {
7250 if (newsrv->minconn > newsrv->maxconn) {
7251 /* Only 'minconn' was specified, or it was higher than or equal
7252 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7253 * this will avoid further useless expensive computations.
7254 */
7255 newsrv->maxconn = newsrv->minconn;
7256 } else if (newsrv->maxconn && !newsrv->minconn) {
7257 /* minconn was not specified, so we set it to maxconn */
7258 newsrv->minconn = newsrv->maxconn;
7259 }
7260
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007261#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007262 if (newsrv->use_ssl || newsrv->check.use_ssl)
7263 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007264#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007265
Willy Tarreau2f075e92013-12-03 11:11:34 +01007266 /* set the check type on the server */
7267 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7268
Willy Tarreau62c3be22012-01-20 13:12:32 +01007269 if (newsrv->trackit) {
7270 struct proxy *px;
7271 struct server *srv;
7272 char *pname, *sname;
7273
7274 pname = newsrv->trackit;
7275 sname = strrchr(pname, '/');
7276
7277 if (sname)
7278 *sname++ = '\0';
7279 else {
7280 sname = pname;
7281 pname = NULL;
7282 }
7283
7284 if (pname) {
7285 px = findproxy(pname, PR_CAP_BE);
7286 if (!px) {
7287 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7288 proxy_type_str(curproxy), curproxy->id,
7289 newsrv->id, pname);
7290 cfgerr++;
7291 goto next_srv;
7292 }
7293 } else
7294 px = curproxy;
7295
7296 srv = findserver(px, sname);
7297 if (!srv) {
7298 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7299 proxy_type_str(curproxy), curproxy->id,
7300 newsrv->id, sname);
7301 cfgerr++;
7302 goto next_srv;
7303 }
7304
Willy Tarreauff5ae352013-12-11 20:36:34 +01007305 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007306 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7307 "tracking as it does not have checks enabled.\n",
7308 proxy_type_str(curproxy), curproxy->id,
7309 newsrv->id, px->id, srv->id);
7310 cfgerr++;
7311 goto next_srv;
7312 }
7313
7314 if (curproxy != px &&
7315 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7316 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7317 "tracking: disable-on-404 option inconsistency.\n",
7318 proxy_type_str(curproxy), curproxy->id,
7319 newsrv->id, px->id, srv->id);
7320 cfgerr++;
7321 goto next_srv;
7322 }
7323
7324 /* if the other server is forced disabled, we have to do the same here */
7325 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007326 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007327 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007328 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007329 }
7330
7331 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007332 newsrv->tracknext = srv->trackers;
7333 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007334
7335 free(newsrv->trackit);
7336 newsrv->trackit = NULL;
7337 }
7338 next_srv:
7339 newsrv = newsrv->next;
7340 }
7341
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007342 /* We have to initialize the server lookup mechanism depending
7343 * on what LB algorithm was choosen.
7344 */
7345
7346 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7347 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7348 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007349 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7350 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7351 init_server_map(curproxy);
7352 } else {
7353 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7354 fwrr_init_server_groups(curproxy);
7355 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007356 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007357
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007358 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007359 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7360 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7361 fwlc_init_server_tree(curproxy);
7362 } else {
7363 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7364 fas_init_server_tree(curproxy);
7365 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007366 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007367
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007368 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007369 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7370 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7371 chash_init_server_tree(curproxy);
7372 } else {
7373 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7374 init_server_map(curproxy);
7375 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007376 break;
7377 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007378
7379 if (curproxy->options & PR_O_LOGASAP)
7380 curproxy->to_log &= ~LW_BYTES;
7381
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007382 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007383 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007384 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7385 proxy_type_str(curproxy), curproxy->id);
7386 err_code |= ERR_WARN;
7387 }
7388
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007389 if (curproxy->mode != PR_MODE_HTTP) {
7390 int optnum;
7391
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007392 if (curproxy->uri_auth) {
7393 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7394 proxy_type_str(curproxy), curproxy->id);
7395 err_code |= ERR_WARN;
7396 curproxy->uri_auth = NULL;
7397 }
7398
Willy Tarreau87cf5142011-08-19 22:57:24 +02007399 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007400 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7401 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7402 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007403 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007404 }
7405
7406 if (curproxy->options & PR_O_ORGTO) {
7407 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7408 "originalto", proxy_type_str(curproxy), curproxy->id);
7409 err_code |= ERR_WARN;
7410 curproxy->options &= ~PR_O_ORGTO;
7411 }
7412
7413 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7414 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7415 (curproxy->cap & cfg_opts[optnum].cap) &&
7416 (curproxy->options & cfg_opts[optnum].val)) {
7417 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7418 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7419 err_code |= ERR_WARN;
7420 curproxy->options &= ~cfg_opts[optnum].val;
7421 }
7422 }
7423
7424 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7425 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7426 (curproxy->cap & cfg_opts2[optnum].cap) &&
7427 (curproxy->options2 & cfg_opts2[optnum].val)) {
7428 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7429 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7430 err_code |= ERR_WARN;
7431 curproxy->options2 &= ~cfg_opts2[optnum].val;
7432 }
7433 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007434
Pieter Baauwd551fb52013-05-08 22:49:23 +02007435#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007436 if (curproxy->conn_src.bind_hdr_occ) {
7437 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007438 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007439 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007440 err_code |= ERR_WARN;
7441 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007442#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007443 }
7444
Willy Tarreaubaaee002006-06-26 02:48:02 +02007445 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007446 * ensure that we're not cross-dressing a TCP server into HTTP.
7447 */
7448 newsrv = curproxy->srv;
7449 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007450 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007451 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7452 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007453 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007454 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007455
Willy Tarreau0cec3312011-10-31 13:49:26 +01007456 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7457 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7458 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7459 err_code |= ERR_WARN;
7460 }
7461
Willy Tarreau82ffa392013-08-13 17:19:08 +02007462 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7463 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7464 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7465 err_code |= ERR_WARN;
7466 }
7467
Pieter Baauwd551fb52013-05-08 22:49:23 +02007468#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007469 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7470 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007471 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 +01007472 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007473 err_code |= ERR_WARN;
7474 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007475#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007476 newsrv = newsrv->next;
7477 }
7478
Willy Tarreauc1a21672009-08-16 22:37:44 +02007479 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007480 if (!curproxy->accept)
7481 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007482
Willy Tarreauc1a21672009-08-16 22:37:44 +02007483 if (curproxy->tcp_req.inspect_delay ||
7484 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007485 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007486
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007487 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007488 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007489 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007490 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007491
7492 /* both TCP and HTTP must check switching rules */
7493 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7494 }
7495
7496 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007497 if (curproxy->tcp_req.inspect_delay ||
7498 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7499 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7500
Emeric Brun97679e72010-09-23 17:56:44 +02007501 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7502 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7503
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007504 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007505 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007506 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007507 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007508
7509 /* If the backend does requires RDP cookie persistence, we have to
7510 * enable the corresponding analyser.
7511 */
7512 if (curproxy->options2 & PR_O2_RDPC_PRST)
7513 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7514 }
7515
Emeric Brunc52962f2012-11-15 18:28:02 +01007516#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007517 /* Configure SSL for each bind line.
7518 * Note: if configuration fails at some point, the ->ctx member
7519 * remains NULL so that listeners can later detach.
7520 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007521 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007522 if (!bind_conf->is_ssl) {
7523 if (bind_conf->default_ctx) {
7524 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7525 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7526 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007527 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007528 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007529 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007530 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007531 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007532 cfgerr++;
7533 continue;
7534 }
7535
Emeric Brun4b3091e2012-09-24 15:48:52 +02007536 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007537 Alert("Unable to allocate SSL session cache.\n");
7538 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007539 continue;
7540 }
7541
Emeric Brunfc0421f2012-09-07 17:30:07 +02007542 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007543 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007544 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007545#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007546
Willy Tarreaue6b98942007-10-29 01:09:36 +01007547 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007548 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007549 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007550 if (!listener->luid) {
7551 /* listener ID not set, use automatic numbering with first
7552 * spare entry starting with next_luid.
7553 */
7554 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7555 listener->conf.id.key = listener->luid = next_id;
7556 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007557 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007558 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007559
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007560 /* enable separate counters */
7561 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7562 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007563 if (!listener->name)
7564 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007565 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007566
Willy Tarreaue6b98942007-10-29 01:09:36 +01007567 if (curproxy->options & PR_O_TCP_NOLING)
7568 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007569 if (!listener->maxconn)
7570 listener->maxconn = curproxy->maxconn;
7571 if (!listener->backlog)
7572 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007573 if (!listener->maxaccept)
7574 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7575
7576 /* we want to have an optimal behaviour on single process mode to
7577 * maximize the work at once, but in multi-process we want to keep
7578 * some fairness between processes, so we target half of the max
7579 * number of events to be balanced over all the processes the proxy
7580 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7581 * used to disable the limit.
7582 */
7583 if (listener->maxaccept > 0) {
7584 if (nbproc > 1)
7585 listener->maxaccept = (listener->maxaccept + 1) / 2;
7586 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7587 }
7588
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007589 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007590 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007591 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007592 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007593
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007594 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7595 listener->options |= LI_O_TCP_RULES;
7596
Willy Tarreaude3041d2010-05-31 10:56:17 +02007597 if (curproxy->mon_mask.s_addr)
7598 listener->options |= LI_O_CHK_MONNET;
7599
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007600 /* smart accept mode is automatic in HTTP mode */
7601 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007602 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007603 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7604 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007605 }
7606
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007607 /* Release unused SSL configs */
7608 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7609 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007610 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007611#ifdef USE_OPENSSL
7612 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007613 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007614 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007615 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007616 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007617#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007618 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007619
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007620 /* Check multi-process mode compatibility for the current proxy */
7621 if (global.nbproc > 1) {
7622 int nbproc = 0;
7623 if (curproxy->bind_proc) {
7624 int proc;
7625 for (proc = 0; proc < global.nbproc; proc++) {
7626 if (curproxy->bind_proc & (1 << proc)) {
7627 nbproc++;
7628 }
7629 }
7630 } else {
7631 nbproc = global.nbproc;
7632 }
7633 if (curproxy->table.peers.name) {
7634 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7635 curproxy->id);
7636 cfgerr++;
7637 }
7638 if (nbproc > 1) {
7639 if (curproxy->uri_auth) {
7640 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7641 curproxy->id);
7642 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7643 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7644 curproxy->id);
7645 }
7646 }
7647 if (curproxy->appsession_name) {
7648 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7649 curproxy->id);
7650 }
7651 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7652 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7653 curproxy->id);
7654 }
7655 }
7656 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007657
7658 /* create the task associated with the proxy */
7659 curproxy->task = task_new();
7660 if (curproxy->task) {
7661 curproxy->task->context = curproxy;
7662 curproxy->task->process = manage_proxy;
7663 /* no need to queue, it will be done automatically if some
7664 * listener gets limited.
7665 */
7666 curproxy->task->expire = TICK_ETERNITY;
7667 } else {
7668 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7669 curproxy->id);
7670 cfgerr++;
7671 }
7672
Willy Tarreaubaaee002006-06-26 02:48:02 +02007673 curproxy = curproxy->next;
7674 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007675
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007676 /* Check multi-process mode compatibility */
7677 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007678 if (global.stats_fe && !global.stats_fe->bind_proc) {
7679 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 +01007680 }
7681 }
7682
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007683 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7684 struct auth_users *curuser;
7685 int g;
7686
7687 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7688 unsigned int group_mask = 0;
7689 char *group = NULL;
7690
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007691 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007692 continue;
7693
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007694 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007695
7696 for (g = 0; g < curuserlist->grpcnt; g++)
7697 if (!strcmp(curuserlist->groups[g], group))
7698 break;
7699
7700 if (g == curuserlist->grpcnt) {
7701 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7702 curuserlist->name, group, curuser->user);
7703 err_code |= ERR_ALERT | ERR_FATAL;
7704 goto out;
7705 }
7706
7707 group_mask |= (1 << g);
7708 }
7709
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007710 free(curuser->u.groups);
7711 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007712 }
7713
7714 for (g = 0; g < curuserlist->grpcnt; g++) {
7715 char *user = NULL;
7716
7717 if (!curuserlist->groupusers[g])
7718 continue;
7719
7720 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7721 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7722 if (!strcmp(curuser->user, user))
7723 break;
7724
7725 if (!curuser) {
7726 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7727 curuserlist->name, user, curuserlist->groups[g]);
7728 err_code |= ERR_ALERT | ERR_FATAL;
7729 goto out;
7730 }
7731
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007732 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007733 }
7734
7735 free(curuserlist->groupusers[g]);
7736 }
7737
7738 free(curuserlist->groupusers);
7739
7740#ifdef DEBUG_AUTH
7741 for (g = 0; g < curuserlist->grpcnt; g++) {
7742 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7743
7744 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007745 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007746 fprintf(stderr, " %s", curuser->user);
7747 }
7748
7749 fprintf(stderr, "\n");
7750 }
7751#endif
7752
Willy Tarreaufbb78422011-06-05 15:38:35 +02007753 }
7754
7755 /* automatically compute fullconn if not set. We must not do it in the
7756 * loop above because cross-references are not yet fully resolved.
7757 */
7758 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7759 /* If <fullconn> is not set, let's set it to 10% of the sum of
7760 * the possible incoming frontend's maxconns.
7761 */
7762 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7763 struct proxy *fe;
7764 int total = 0;
7765
7766 /* sum up the number of maxconns of frontends which
7767 * reference this backend at least once or which are
7768 * the same one ('listen').
7769 */
7770 for (fe = proxy; fe; fe = fe->next) {
7771 struct switching_rule *rule;
7772 struct hdr_exp *exp;
7773 int found = 0;
7774
7775 if (!(fe->cap & PR_CAP_FE))
7776 continue;
7777
7778 if (fe == curproxy) /* we're on a "listen" instance */
7779 found = 1;
7780
7781 if (fe->defbe.be == curproxy) /* "default_backend" */
7782 found = 1;
7783
7784 /* check if a "use_backend" rule matches */
7785 if (!found) {
7786 list_for_each_entry(rule, &fe->switching_rules, list) {
7787 if (rule->be.backend == curproxy) {
7788 found = 1;
7789 break;
7790 }
7791 }
7792 }
7793
7794 /* check if a "reqsetbe" rule matches */
7795 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7796 if (exp->action == ACT_SETBE &&
7797 (struct proxy *)exp->replace == curproxy) {
7798 found = 1;
7799 break;
7800 }
7801 }
7802
7803 /* now we've checked all possible ways to reference a backend
7804 * from a frontend.
7805 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007806 if (!found)
7807 continue;
7808 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007809 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007810 /* we have the sum of the maxconns in <total>. We only
7811 * keep 10% of that sum to set the default fullconn, with
7812 * a hard minimum of 1 (to avoid a divide by zero).
7813 */
7814 curproxy->fullconn = (total + 9) / 10;
7815 if (!curproxy->fullconn)
7816 curproxy->fullconn = 1;
7817 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007818 }
7819
Willy Tarreau056f5682010-06-06 15:51:11 +02007820 /* initialize stick-tables on backend capable proxies. This must not
7821 * be done earlier because the data size may be discovered while parsing
7822 * other proxies.
7823 */
Godbach9703e662013-12-11 21:11:41 +08007824 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007825 if (curproxy->state == PR_STSTOPPED)
7826 continue;
7827
Godbach9703e662013-12-11 21:11:41 +08007828 if (!stktable_init(&curproxy->table)) {
7829 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7830 cfgerr++;
7831 }
7832 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007833
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007834 /*
7835 * Recount currently required checks.
7836 */
7837
7838 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7839 int optnum;
7840
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007841 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7842 if (curproxy->options & cfg_opts[optnum].val)
7843 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007844
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007845 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7846 if (curproxy->options2 & cfg_opts2[optnum].val)
7847 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007848 }
7849
Willy Tarreau122541c2011-09-07 21:24:49 +02007850 if (peers) {
7851 struct peers *curpeers = peers, **last;
7852 struct peer *p, *pb;
7853
7854 /* Remove all peers sections which don't have a valid listener.
7855 * This can happen when a peers section is never referenced and
7856 * does not contain a local peer.
7857 */
7858 last = &peers;
7859 while (*last) {
7860 curpeers = *last;
7861 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007862 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007863 last = &curpeers->next;
7864 continue;
7865 }
7866
7867 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7868 curpeers->id, localpeer);
7869
7870 p = curpeers->remote;
7871 while (p) {
7872 pb = p->next;
7873 free(p->id);
7874 free(p);
7875 p = pb;
7876 }
7877
7878 /* Destroy and unlink this curpeers section.
7879 * Note: curpeers is backed up into *last.
7880 */
7881 free(curpeers->id);
7882 curpeers = curpeers->next;
7883 free(*last);
7884 *last = curpeers;
7885 }
7886 }
7887
Willy Tarreau34eb6712011-10-24 18:15:04 +02007888 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007889 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007890 MEM_F_SHARED);
7891
Willy Tarreaubb925012009-07-23 13:36:36 +02007892 if (cfgerr > 0)
7893 err_code |= ERR_ALERT | ERR_FATAL;
7894 out:
7895 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007896}
7897
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007898/*
7899 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7900 * parsing sessions.
7901 */
7902void cfg_register_keywords(struct cfg_kw_list *kwl)
7903{
7904 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7905}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007906
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007907/*
7908 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7909 */
7910void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7911{
7912 LIST_DEL(&kwl->list);
7913 LIST_INIT(&kwl->list);
7914}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007915
7916/*
7917 * Local variables:
7918 * c-indent-level: 8
7919 * c-basic-offset: 8
7920 * End:
7921 */