blob: 4d1ecd02a495cc440e28b432622e07788be6d617 [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 },
132 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
133 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
134 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau16bfb022010-01-16 19:48:41 +0100135 { "http-keep-alive", PR_O_KEEPALIVE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100136 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100137 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100138 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
139 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
140 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
141 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
142 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100143#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100145#else
146 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100147#endif
148
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150};
151
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100152/* proxy->options2 */
153static const struct cfg_opt cfg_opts2[] =
154{
155#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
157 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
158 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100159#else
160 { "splice-request", 0, 0, 0, 0 },
161 { "splice-response", 0, 0, 0, 0 },
162 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100163#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
165 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
166 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
167 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
168 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
169 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
170 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
171 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
172 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400173 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200175 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200176 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100177 { NULL, 0, 0, 0 }
178};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179
Willy Tarreau6daf3432008-01-22 16:44:08 +0100180static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
182int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100183int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200184
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200185/* List head of all known configuration keywords */
186static struct cfg_kw_list cfg_keywords = {
187 .list = LIST_HEAD_INIT(cfg_keywords.list)
188};
189
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190/*
191 * converts <str> to a list of listeners which are dynamically allocated.
192 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
193 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
194 * - <port> is a numerical port from 1 to 65535 ;
195 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
196 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
198 * not NULL, it must be a valid pointer to either NULL or a freeable area that
199 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200201int 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 +0200202{
203 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100204 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 int port, end;
206
207 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200208
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100210 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100211 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212
213 str = next;
214 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100215 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216 *next++ = 0;
217 }
218
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100219 ss2 = str2sa_range(str, &port, &end, err,
220 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
221 if (!ss2)
222 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100224 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100225 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200226 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100227 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100230 if (!port || !end) {
231 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
232 goto fail;
233 }
234
Emeric Bruned760922010-10-22 17:59:25 +0200235 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200236 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200237 goto fail;
238 }
239
240 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200241 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200242 goto fail;
243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100245 else if (ss2->ss_family == AF_UNSPEC) {
246 socklen_t addr_len;
247
248 /* We want to attach to an already bound fd whose number
249 * is in the addr part of ss2 when cast to sockaddr_in.
250 * Note that by definition there is a single listener.
251 * We still have to determine the address family to
252 * register the correct protocol.
253 */
254 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
255 addr_len = sizeof(*ss2);
256 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
257 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
258 goto fail;
259 }
260
261 port = end = get_host_port(ss2);
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100264 /* OK the address looks correct */
265 ss = *ss2;
266
Willy Tarreaubaaee002006-06-26 02:48:02 +0200267 for (; port <= end; port++) {
268 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100269 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200270 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
271 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
272 l->frontend = curproxy;
273 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200274
Willy Tarreau40aa0702013-03-10 23:51:38 +0100275 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200276 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200277 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 l->state = LI_INIT;
279
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100280 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100282 tcpv4_add_listener(l);
283 }
Emeric Bruned760922010-10-22 17:59:25 +0200284 else if (ss.ss_family == AF_INET6) {
285 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
286 tcpv6_add_listener(l);
287 }
288 else {
Emeric Bruned760922010-10-22 17:59:25 +0200289 uxst_add_listener(l);
290 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200292 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100293 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 } /* end for(port) */
295 } /* end while(next) */
296 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200297 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 fail:
299 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200300 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301}
302
Willy Tarreau977b8e42006-12-29 14:19:17 +0100303/*
304 * Sends a warning if proxy <proxy> does not have at least one of the
305 * capabilities in <cap>. An optionnal <hint> may be added at the end
306 * of the warning to help the user. Returns 1 if a warning was emitted
307 * or 0 if the condition is valid.
308 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100309int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100310{
311 char *msg;
312
313 switch (cap) {
314 case PR_CAP_BE: msg = "no backend"; break;
315 case PR_CAP_FE: msg = "no frontend"; break;
316 case PR_CAP_RS: msg = "no ruleset"; break;
317 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
318 default: msg = "not enough"; break;
319 }
320
321 if (!(proxy->cap & cap)) {
322 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100323 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100324 return 1;
325 }
326 return 0;
327}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200328
Willy Tarreau61d18892009-03-31 10:49:21 +0200329/* Report a warning if a rule is placed after a 'block' rule.
330 * Return 1 if the warning has been emitted, otherwise 0.
331 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100332int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200333{
334 if (!LIST_ISEMPTY(&proxy->block_cond)) {
335 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
336 file, line, arg);
337 return 1;
338 }
339 return 0;
340}
341
342/* Report a warning if a rule is placed after a reqrewrite rule.
343 * Return 1 if the warning has been emitted, otherwise 0.
344 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100345int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200346{
347 if (proxy->req_exp) {
348 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
349 file, line, arg);
350 return 1;
351 }
352 return 0;
353}
354
355/* Report a warning if a rule is placed after a reqadd rule.
356 * Return 1 if the warning has been emitted, otherwise 0.
357 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100358int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200359{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100360 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200361 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
362 file, line, arg);
363 return 1;
364 }
365 return 0;
366}
367
368/* Report a warning if a rule is placed after a redirect rule.
369 * Return 1 if the warning has been emitted, otherwise 0.
370 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100371int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200372{
373 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
374 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
375 file, line, arg);
376 return 1;
377 }
378 return 0;
379}
380
381/* Report a warning if a rule is placed after a 'use_backend' rule.
382 * Return 1 if the warning has been emitted, otherwise 0.
383 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100384int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200385{
386 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
387 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
388 file, line, arg);
389 return 1;
390 }
391 return 0;
392}
393
394/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
398 warnif_rule_after_reqadd(proxy, file, line, arg) ||
399 warnif_rule_after_redirect(proxy, file, line, arg) ||
400 warnif_rule_after_use_backend(proxy, file, line, arg);
401}
402
403/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100404int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200405{
406 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
407 warnif_rule_after_redirect(proxy, file, line, arg) ||
408 warnif_rule_after_use_backend(proxy, file, line, arg);
409}
410
411/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
414 return warnif_rule_after_redirect(proxy, file, line, arg) ||
415 warnif_rule_after_use_backend(proxy, file, line, arg);
416}
417
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100418/* Report it if a request ACL condition uses some keywords that are incompatible
419 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
420 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
421 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100422 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100423static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100424{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100425 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200426 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100427
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100428 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100429 return 0;
430
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100431 acl = acl_cond_conflicts(cond, where);
432 if (acl) {
433 if (acl->name && *acl->name)
434 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
435 file, line, acl->name, sample_ckp_names(where));
436 else
437 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 +0200438 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100439 return ERR_WARN;
440 }
441 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100442 return 0;
443
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100444 if (acl->name && *acl->name)
445 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200446 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100447 else
448 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200449 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100450 return ERR_WARN;
451}
452
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200454 * parse a line in a <global> section. Returns the error code, 0 if OK, or
455 * any combination of :
456 * - ERR_ABORT: must abort ASAP
457 * - ERR_FATAL: we can continue parsing but not start the service
458 * - ERR_WARN: a warning has been emitted
459 * - ERR_ALERT: an alert has been emitted
460 * Only the two first ones can stop processing, the two others are just
461 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200462 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200463int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200464{
Willy Tarreau058e9072009-07-20 09:30:05 +0200465 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200466 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467
468 if (!strcmp(args[0], "global")) { /* new section */
469 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200472 else if (!strcmp(args[0], "ca-base")) {
473#ifdef USE_OPENSSL
474 if (global.ca_base != NULL) {
475 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
476 err_code |= ERR_ALERT;
477 goto out;
478 }
479 if (*(args[1]) == 0) {
480 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT | ERR_FATAL;
482 goto out;
483 }
484 global.ca_base = strdup(args[1]);
485#else
486 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
487 err_code |= ERR_ALERT | ERR_FATAL;
488 goto out;
489#endif
490 }
491 else if (!strcmp(args[0], "crt-base")) {
492#ifdef USE_OPENSSL
493 if (global.crt_base != NULL) {
494 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
495 err_code |= ERR_ALERT;
496 goto out;
497 }
498 if (*(args[1]) == 0) {
499 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
500 err_code |= ERR_ALERT | ERR_FATAL;
501 goto out;
502 }
503 global.crt_base = strdup(args[1]);
504#else
505 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
506 err_code |= ERR_ALERT | ERR_FATAL;
507 goto out;
508#endif
509 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200510 else if (!strcmp(args[0], "daemon")) {
511 global.mode |= MODE_DAEMON;
512 }
513 else if (!strcmp(args[0], "debug")) {
514 global.mode |= MODE_DEBUG;
515 }
516 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100517 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200519 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100520 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200521 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200522 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100523 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100525 else if (!strcmp(args[0], "nosplice")) {
526 global.tune.options &= ~GTUNE_USE_SPLICE;
527 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200528 else if (!strcmp(args[0], "quiet")) {
529 global.mode |= MODE_QUIET;
530 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200531 else if (!strcmp(args[0], "tune.maxpollevents")) {
532 if (global.tune.maxpollevents != 0) {
533 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200534 err_code |= ERR_ALERT;
535 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200536 }
537 if (*(args[1]) == 0) {
538 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200539 err_code |= ERR_ALERT | ERR_FATAL;
540 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200541 }
542 global.tune.maxpollevents = atol(args[1]);
543 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100544 else if (!strcmp(args[0], "tune.maxaccept")) {
545 if (global.tune.maxaccept != 0) {
546 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 err_code |= ERR_ALERT;
548 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100549 }
550 if (*(args[1]) == 0) {
551 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100554 }
555 global.tune.maxaccept = atol(args[1]);
556 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200557 else if (!strcmp(args[0], "tune.chksize")) {
558 if (*(args[1]) == 0) {
559 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
560 err_code |= ERR_ALERT | ERR_FATAL;
561 goto out;
562 }
563 global.tune.chksize = atol(args[1]);
564 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200565#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100566 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200567 if (*(args[1]) == 0) {
568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT | ERR_FATAL;
570 goto out;
571 }
572 global.tune.sslcachesize = atol(args[1]);
573 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100574 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
575 unsigned int ssllifetime;
576 const char *res;
577
578 if (*(args[1]) == 0) {
579 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
580 err_code |= ERR_ALERT | ERR_FATAL;
581 goto out;
582 }
583
584 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
585 if (res) {
586 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
587 file, linenum, *res, args[0]);
588 err_code |= ERR_ALERT | ERR_FATAL;
589 goto out;
590 }
591
592 global.tune.ssllifetime = ssllifetime;
593 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100594 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.tune.ssl_max_record = atol(args[1]);
601 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200602#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200603 else if (!strcmp(args[0], "tune.bufsize")) {
604 if (*(args[1]) == 0) {
605 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
606 err_code |= ERR_ALERT | ERR_FATAL;
607 goto out;
608 }
609 global.tune.bufsize = atol(args[1]);
610 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
611 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100612 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100613 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200614 }
615 else if (!strcmp(args[0], "tune.maxrewrite")) {
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.tune.maxrewrite = atol(args[1]);
622 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
623 global.tune.maxrewrite = global.tune.bufsize / 2;
624 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100625 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
626 if (global.tune.client_rcvbuf != 0) {
627 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT;
629 goto out;
630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
635 }
636 global.tune.client_rcvbuf = atol(args[1]);
637 }
638 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
639 if (global.tune.server_rcvbuf != 0) {
640 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT;
642 goto out;
643 }
644 if (*(args[1]) == 0) {
645 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
646 err_code |= ERR_ALERT | ERR_FATAL;
647 goto out;
648 }
649 global.tune.server_rcvbuf = atol(args[1]);
650 }
651 else if (!strcmp(args[0], "tune.sndbuf.client")) {
652 if (global.tune.client_sndbuf != 0) {
653 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT;
655 goto out;
656 }
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
661 }
662 global.tune.client_sndbuf = atol(args[1]);
663 }
664 else if (!strcmp(args[0], "tune.sndbuf.server")) {
665 if (global.tune.server_sndbuf != 0) {
666 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
667 err_code |= ERR_ALERT;
668 goto out;
669 }
670 if (*(args[1]) == 0) {
671 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675 global.tune.server_sndbuf = atol(args[1]);
676 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200677 else if (!strcmp(args[0], "tune.pipesize")) {
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.pipesize = atol(args[1]);
684 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100685 else if (!strcmp(args[0], "tune.http.cookielen")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.cookie_len = atol(args[1]) + 1;
692 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200693 else if (!strcmp(args[0], "tune.http.maxhdr")) {
694 if (*(args[1]) == 0) {
695 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
696 err_code |= ERR_ALERT | ERR_FATAL;
697 goto out;
698 }
699 global.tune.max_http_hdr = atol(args[1]);
700 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100701 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
702#ifdef USE_ZLIB
703 if (*args[1]) {
704 global.tune.zlibmemlevel = atoi(args[1]);
705 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
706 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
707 file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
711 } else {
712 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
713 file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717#else
718 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721#endif
722 }
723 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
724#ifdef USE_ZLIB
725 if (*args[1]) {
726 global.tune.zlibwindowsize = atoi(args[1]);
727 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
728 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
729 file, linenum, args[0]);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733 } else {
734 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
735 file, linenum, args[0]);
736 err_code |= ERR_ALERT | ERR_FATAL;
737 goto out;
738 }
739#else
740 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743#endif
744 }
William Lallemandf3747832012-11-09 12:33:10 +0100745 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
746 if (*args[1]) {
747 global.tune.comp_maxlevel = atoi(args[1]);
748 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
749 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\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 1 and 9\n",
756 file, linenum, args[0]);
757 err_code |= ERR_ALERT | ERR_FATAL;
758 goto out;
759 }
760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200761 else if (!strcmp(args[0], "uid")) {
762 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200763 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200764 err_code |= ERR_ALERT;
765 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200766 }
767 if (*(args[1]) == 0) {
768 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200771 }
772 global.uid = atol(args[1]);
773 }
774 else if (!strcmp(args[0], "gid")) {
775 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200776 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200777 err_code |= ERR_ALERT;
778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200779 }
780 if (*(args[1]) == 0) {
781 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200784 }
785 global.gid = atol(args[1]);
786 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200787 /* user/group name handling */
788 else if (!strcmp(args[0], "user")) {
789 struct passwd *ha_user;
790 if (global.uid != 0) {
791 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200792 err_code |= ERR_ALERT;
793 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200794 }
795 errno = 0;
796 ha_user = getpwnam(args[1]);
797 if (ha_user != NULL) {
798 global.uid = (int)ha_user->pw_uid;
799 }
800 else {
801 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 +0200802 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200803 }
804 }
805 else if (!strcmp(args[0], "group")) {
806 struct group *ha_group;
807 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200808 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200809 err_code |= ERR_ALERT;
810 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200811 }
812 errno = 0;
813 ha_group = getgrnam(args[1]);
814 if (ha_group != NULL) {
815 global.gid = (int)ha_group->gr_gid;
816 }
817 else {
818 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 +0200819 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200820 }
821 }
822 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200823 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 if (*(args[1]) == 0) {
825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200826 err_code |= ERR_ALERT | ERR_FATAL;
827 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200828 }
829 global.nbproc = atol(args[1]);
830 }
831 else if (!strcmp(args[0], "maxconn")) {
832 if (global.maxconn != 0) {
833 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200834 err_code |= ERR_ALERT;
835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200836 }
837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200841 }
842 global.maxconn = atol(args[1]);
843#ifdef SYSTEM_MAXCONN
844 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
845 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);
846 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200847 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200848 }
849#endif /* SYSTEM_MAXCONN */
850 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200851 else if (!strcmp(args[0], "maxsslconn")) {
852#ifdef USE_OPENSSL
853 if (*(args[1]) == 0) {
854 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858 global.maxsslconn = atol(args[1]);
859#else
Emeric Brun0914df82012-10-02 18:45:42 +0200860 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200863#endif
864 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200865 else if (!strcmp(args[0], "maxconnrate")) {
866 if (global.cps_lim != 0) {
867 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT;
869 goto out;
870 }
871 if (*(args[1]) == 0) {
872 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
875 }
876 global.cps_lim = atol(args[1]);
877 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200878 else if (!strcmp(args[0], "maxsessrate")) {
879 if (global.sps_lim != 0) {
880 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
881 err_code |= ERR_ALERT;
882 goto out;
883 }
884 if (*(args[1]) == 0) {
885 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
886 err_code |= ERR_ALERT | ERR_FATAL;
887 goto out;
888 }
889 global.sps_lim = atol(args[1]);
890 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200891 else if (!strcmp(args[0], "maxsslrate")) {
892 if (global.ssl_lim != 0) {
893 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT;
895 goto out;
896 }
897 if (*(args[1]) == 0) {
898 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 global.ssl_lim = atol(args[1]);
903 }
William Lallemandd85f9172012-11-09 17:05:39 +0100904 else if (!strcmp(args[0], "maxcomprate")) {
905 if (*(args[1]) == 0) {
906 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
907 err_code |= ERR_ALERT | ERR_FATAL;
908 goto out;
909 }
910 global.comp_rate_lim = atoi(args[1]) * 1024;
911 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100912 else if (!strcmp(args[0], "maxpipes")) {
913 if (global.maxpipes != 0) {
914 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200915 err_code |= ERR_ALERT;
916 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100917 }
918 if (*(args[1]) == 0) {
919 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200920 err_code |= ERR_ALERT | ERR_FATAL;
921 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100922 }
923 global.maxpipes = atol(args[1]);
924 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100925 else if (!strcmp(args[0], "maxzlibmem")) {
926 if (*(args[1]) == 0) {
927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
William Lallemande3a7d992012-11-20 11:25:20 +0100931 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100932 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100933 else if (!strcmp(args[0], "maxcompcpuusage")) {
934 if (*(args[1]) == 0) {
935 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
936 err_code |= ERR_ALERT | ERR_FATAL;
937 goto out;
938 }
939 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100940 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100941 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto out;
944 }
945}
946
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947 else if (!strcmp(args[0], "ulimit-n")) {
948 if (global.rlimit_nofile != 0) {
949 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200950 err_code |= ERR_ALERT;
951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 }
953 if (*(args[1]) == 0) {
954 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200955 err_code |= ERR_ALERT | ERR_FATAL;
956 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 global.rlimit_nofile = atol(args[1]);
959 }
960 else if (!strcmp(args[0], "chroot")) {
961 if (global.chroot != NULL) {
962 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200963 err_code |= ERR_ALERT;
964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 }
966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 global.chroot = strdup(args[1]);
972 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200973 else if (!strcmp(args[0], "description")) {
974 int i, len=0;
975 char *d;
976
977 if (!*args[1]) {
978 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
979 file, linenum, args[0]);
980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
982 }
983
984 for(i=1; *args[i]; i++)
985 len += strlen(args[i])+1;
986
987 if (global.desc)
988 free(global.desc);
989
990 global.desc = d = (char *)calloc(1, len);
991
992 d += sprintf(d, "%s", args[1]);
993 for(i=2; *args[i]; i++)
994 d += sprintf(d, " %s", args[i]);
995 }
996 else if (!strcmp(args[0], "node")) {
997 int i;
998 char c;
999
1000 for (i=0; args[1][i]; i++) {
1001 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001002 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1003 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001004 break;
1005 }
1006
1007 if (!i || args[1][i]) {
1008 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1009 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1010 file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014
1015 if (global.node)
1016 free(global.node);
1017
1018 global.node = strdup(args[1]);
1019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001020 else if (!strcmp(args[0], "pidfile")) {
1021 if (global.pidfile != NULL) {
1022 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001023 err_code |= ERR_ALERT;
1024 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001025 }
1026 if (*(args[1]) == 0) {
1027 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001028 err_code |= ERR_ALERT | ERR_FATAL;
1029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030 }
1031 global.pidfile = strdup(args[1]);
1032 }
Emeric Bruned760922010-10-22 17:59:25 +02001033 else if (!strcmp(args[0], "unix-bind")) {
1034 int cur_arg = 1;
1035 while (*(args[cur_arg])) {
1036 if (!strcmp(args[cur_arg], "prefix")) {
1037 if (global.unix_bind.prefix != NULL) {
1038 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1039 err_code |= ERR_ALERT;
1040 cur_arg += 2;
1041 continue;
1042 }
1043
1044 if (*(args[cur_arg+1]) == 0) {
1045 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
1048 }
1049 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1050 cur_arg += 2;
1051 continue;
1052 }
1053
1054 if (!strcmp(args[cur_arg], "mode")) {
1055
1056 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1057 cur_arg += 2;
1058 continue;
1059 }
1060
1061 if (!strcmp(args[cur_arg], "uid")) {
1062
1063 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1064 cur_arg += 2;
1065 continue;
1066 }
1067
1068 if (!strcmp(args[cur_arg], "gid")) {
1069
1070 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1071 cur_arg += 2;
1072 continue;
1073 }
1074
1075 if (!strcmp(args[cur_arg], "user")) {
1076 struct passwd *user;
1077
1078 user = getpwnam(args[cur_arg + 1]);
1079 if (!user) {
1080 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1081 file, linenum, args[0], args[cur_arg + 1 ]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085
1086 global.unix_bind.ux.uid = user->pw_uid;
1087 cur_arg += 2;
1088 continue;
1089 }
1090
1091 if (!strcmp(args[cur_arg], "group")) {
1092 struct group *group;
1093
1094 group = getgrnam(args[cur_arg + 1]);
1095 if (!group) {
1096 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1097 file, linenum, args[0], args[cur_arg + 1 ]);
1098 err_code |= ERR_ALERT | ERR_FATAL;
1099 goto out;
1100 }
1101
1102 global.unix_bind.ux.gid = group->gr_gid;
1103 cur_arg += 2;
1104 continue;
1105 }
1106
Willy Tarreaub48f9582011-09-05 01:17:06 +02001107 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001108 file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 }
William Lallemand0f99e342011-10-12 17:50:54 +02001113 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1114 /* delete previous herited or defined syslog servers */
1115 struct logsrv *back;
1116 struct logsrv *tmp;
1117
1118 if (*(args[1]) != 0) {
1119 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123
1124 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1125 LIST_DEL(&tmp->list);
1126 free(tmp);
1127 }
1128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001129 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001130 struct sockaddr_storage *sk;
1131 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001132 struct logsrv *logsrv;
1133
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 if (*(args[1]) == 0 || *(args[2]) == 0) {
1135 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
1137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 }
William Lallemand0f99e342011-10-12 17:50:54 +02001139
1140 logsrv = calloc(1, sizeof(struct logsrv));
1141
1142 logsrv->facility = get_log_facility(args[2]);
1143 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001146 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 }
1148
William Lallemand0f99e342011-10-12 17:50:54 +02001149 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001151 logsrv->level = get_log_level(args[3]);
1152 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001155 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 }
1158
William Lallemand0f99e342011-10-12 17:50:54 +02001159 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001160 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001161 logsrv->minlvl = get_log_level(args[4]);
1162 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001163 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001164 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001165 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001166 }
1167 }
1168
Willy Tarreau902636f2013-03-10 19:44:48 +01001169 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001170 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001171 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001172 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001173 free(logsrv);
1174 goto out;
1175 }
1176 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001177
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001178 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001179 if (port1 != port2) {
1180 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1181 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001182 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001183 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001184 goto out;
1185 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001186
William Lallemand0f99e342011-10-12 17:50:54 +02001187 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001188 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001189 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001191
William Lallemand0f99e342011-10-12 17:50:54 +02001192 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001193 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001194 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1195 char *name;
1196 int len;
1197
1198 if (global.log_send_hostname != NULL) {
1199 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1200 err_code |= ERR_ALERT;
1201 goto out;
1202 }
1203
1204 if (*(args[1]))
1205 name = args[1];
1206 else
1207 name = hostname;
1208
1209 len = strlen(name);
1210
1211 /* We'll add a space after the name to respect the log format */
1212 free(global.log_send_hostname);
1213 global.log_send_hostname = malloc(len + 2);
1214 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1215 }
Kevinm48936af2010-12-22 16:08:21 +00001216 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1217 if (*(args[1]) == 0) {
1218 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222 free(global.log_tag);
1223 global.log_tag = strdup(args[1]);
1224 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001225 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1226 if (global.spread_checks != 0) {
1227 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001228 err_code |= ERR_ALERT;
1229 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001230 }
1231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001235 }
1236 global.spread_checks = atol(args[1]);
1237 if (global.spread_checks < 0 || global.spread_checks > 50) {
1238 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001239 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001240 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001241 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001242 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1243#ifdef USE_CPU_AFFINITY
1244 int cur_arg, i;
1245 unsigned int proc = 0;
1246 unsigned long cpus = 0;
1247
1248 if (strcmp(args[1], "all") == 0)
1249 proc = 0xFFFFFFFF;
1250 else if (strcmp(args[1], "odd") == 0)
1251 proc = 0x55555555;
1252 else if (strcmp(args[1], "even") == 0)
1253 proc = 0xAAAAAAAA;
1254 else {
1255 proc = atoi(args[1]);
1256 if (proc >= 1 && proc <= 32)
1257 proc = 1 << (proc - 1);
1258 }
1259
1260 if (!proc || !*args[2]) {
1261 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",
1262 file, linenum, args[0]);
1263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
1265 }
1266
1267 cur_arg = 2;
1268 while (*args[cur_arg]) {
1269 unsigned int low, high;
1270
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001271 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001272 char *dash = strchr(args[cur_arg], '-');
1273
1274 low = high = str2uic(args[cur_arg]);
1275 if (dash)
1276 high = str2uic(dash + 1);
1277
1278 if (high < low) {
1279 unsigned int swap = low;
1280 low = high;
1281 high = swap;
1282 }
1283
1284 if (low < 0 || high >= sizeof(long) * 8) {
1285 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1286 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290
1291 while (low <= high)
1292 cpus |= 1UL << low++;
1293 }
1294 else {
1295 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1296 file, linenum, args[0], args[cur_arg]);
1297 err_code |= ERR_ALERT | ERR_FATAL;
1298 goto out;
1299 }
1300 cur_arg++;
1301 }
1302 for (i = 0; i < 32; i++)
1303 if (proc & (1 << i))
1304 global.cpu_map[i] = cpus;
1305#else
1306 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1307 err_code |= ERR_ALERT | ERR_FATAL;
1308 goto out;
1309#endif
1310 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001311 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001312 struct cfg_kw_list *kwl;
1313 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001314 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001315
1316 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1317 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1318 if (kwl->kw[index].section != CFG_GLOBAL)
1319 continue;
1320 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001321 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001322 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001323 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001325 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001326 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001327 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001328 err_code |= ERR_WARN;
1329 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001330 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001331 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001332 }
1333 }
1334 }
1335
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001337 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001339
Willy Tarreau058e9072009-07-20 09:30:05 +02001340 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001341 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343}
1344
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001345void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001347 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 defproxy.mode = PR_MODE_TCP;
1349 defproxy.state = PR_STNEW;
1350 defproxy.maxconn = cfg_maxpconn;
1351 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001352
Simon Horman66183002013-02-23 10:16:43 +09001353 defproxy.defsrv.check.inter = DEF_CHKINTR;
1354 defproxy.defsrv.check.fastinter = 0;
1355 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001356 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1357 defproxy.defsrv.agent.fastinter = 0;
1358 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001359 defproxy.defsrv.check.rise = DEF_RISETIME;
1360 defproxy.defsrv.check.fall = DEF_FALLTIME;
1361 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1362 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001363 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001364 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001365 defproxy.defsrv.maxqueue = 0;
1366 defproxy.defsrv.minconn = 0;
1367 defproxy.defsrv.maxconn = 0;
1368 defproxy.defsrv.slowstart = 0;
1369 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1370 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1371 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001372}
1373
Willy Tarreauade5ec42010-01-28 19:33:49 +01001374
1375static int create_cond_regex_rule(const char *file, int line,
1376 struct proxy *px, int dir, int action, int flags,
1377 const char *cmd, const char *reg, const char *repl,
1378 const char **cond_start)
1379{
1380 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001381 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001382 const char *err;
1383 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001384 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001385
1386 if (px == &defproxy) {
1387 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1388 err_code |= ERR_ALERT | ERR_FATAL;
1389 goto err;
1390 }
1391
1392 if (*reg == 0) {
1393 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1394 err_code |= ERR_ALERT | ERR_FATAL;
1395 goto err;
1396 }
1397
1398 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1399 err_code |= ERR_WARN;
1400
Willy Tarreau5321c422010-01-28 20:35:13 +01001401 if (cond_start &&
1402 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001403 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1404 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1405 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto err;
1408 }
1409 }
1410 else if (cond_start && **cond_start) {
1411 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1412 file, line, cmd, *cond_start);
1413 err_code |= ERR_ALERT | ERR_FATAL;
1414 goto err;
1415 }
1416
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001417 err_code |= warnif_cond_conflicts(cond,
1418 (dir == SMP_OPT_DIR_REQ) ?
1419 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1420 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1421 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001422
Willy Tarreauade5ec42010-01-28 19:33:49 +01001423 preg = calloc(1, sizeof(regex_t));
1424 if (!preg) {
1425 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1426 err_code = ERR_ALERT | ERR_FATAL;
1427 goto err;
1428 }
1429
1430 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1431 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1432 err_code = ERR_ALERT | ERR_FATAL;
1433 goto err;
1434 }
1435
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001436 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001437 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001438 if (repl && err) {
1439 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1440 file, line, cmd, *err);
1441 err_code |= ERR_ALERT | ERR_FATAL;
1442 goto err;
1443 }
1444
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001445 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001446 err_code |= ERR_WARN;
1447
Willy Tarreauf4068b62012-05-08 17:37:49 +02001448 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001449 return err_code;
1450 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001451 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001452 free(preg);
1453 return err_code;
1454}
1455
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001457 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001458 * Returns the error code, 0 if OK, or any combination of :
1459 * - ERR_ABORT: must abort ASAP
1460 * - ERR_FATAL: we can continue parsing but not start the service
1461 * - ERR_WARN: a warning has been emitted
1462 * - ERR_ALERT: an alert has been emitted
1463 * Only the two first ones can stop processing, the two others are just
1464 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001466int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1467{
1468 static struct peers *curpeers = NULL;
1469 struct peer *newpeer = NULL;
1470 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001471 struct bind_conf *bind_conf;
1472 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001473 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001474 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001475
1476 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001477 if (!*args[1]) {
1478 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1479 err_code |= ERR_ALERT | ERR_FATAL;
1480 goto out;
1481 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001482
1483 err = invalid_char(args[1]);
1484 if (err) {
1485 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1486 file, linenum, *err, args[0], args[1]);
1487 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001488 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001489 }
1490
1491 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1492 /*
1493 * If there are two proxies with the same name only following
1494 * combinations are allowed:
1495 */
1496 if (strcmp(curpeers->id, args[1]) == 0) {
1497 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1498 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1499 err_code |= ERR_WARN;
1500 }
1501 }
1502
1503 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1504 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1505 err_code |= ERR_ALERT | ERR_ABORT;
1506 goto out;
1507 }
1508
1509 curpeers->next = peers;
1510 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001511 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001512 curpeers->conf.line = linenum;
1513 curpeers->last_change = now.tv_sec;
1514 curpeers->id = strdup(args[1]);
1515 }
1516 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001517 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001518 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001519 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001520
1521 if (!*args[2]) {
1522 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1523 file, linenum, args[0]);
1524 err_code |= ERR_ALERT | ERR_FATAL;
1525 goto out;
1526 }
1527
1528 err = invalid_char(args[1]);
1529 if (err) {
1530 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1531 file, linenum, *err, args[1]);
1532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
1534 }
1535
1536 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1537 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1538 err_code |= ERR_ALERT | ERR_ABORT;
1539 goto out;
1540 }
1541
1542 /* the peers are linked backwards first */
1543 curpeers->count++;
1544 newpeer->next = curpeers->remote;
1545 curpeers->remote = newpeer;
1546 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001547 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001548 newpeer->conf.line = linenum;
1549
1550 newpeer->last_change = now.tv_sec;
1551 newpeer->id = strdup(args[1]);
1552
Willy Tarreau902636f2013-03-10 19:44:48 +01001553 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001554 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001555 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001558 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001559
1560 proto = protocol_by_family(sk->ss_family);
1561 if (!proto || !proto->connect) {
1562 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1563 file, linenum, args[0], args[1]);
1564 err_code |= ERR_ALERT | ERR_FATAL;
1565 goto out;
1566 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001567
1568 if (port1 != port2) {
1569 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1570 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001571 err_code |= ERR_ALERT | ERR_FATAL;
1572 goto out;
1573 }
1574
Willy Tarreau2aa38802013-02-20 19:20:59 +01001575 if (!port1) {
1576 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1577 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001578 err_code |= ERR_ALERT | ERR_FATAL;
1579 goto out;
1580 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001581
Emeric Brun32da3c42010-09-23 18:39:19 +02001582 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001583 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001584 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001585 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001586
Emeric Brun32da3c42010-09-23 18:39:19 +02001587 if (strcmp(newpeer->id, localpeer) == 0) {
1588 /* Current is local peer, it define a frontend */
1589 newpeer->local = 1;
1590
1591 if (!curpeers->peers_fe) {
1592 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1593 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1594 err_code |= ERR_ALERT | ERR_ABORT;
1595 goto out;
1596 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001597
Willy Tarreau237250c2011-07-29 01:49:03 +02001598 init_new_proxy(curpeers->peers_fe);
1599 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001600
1601 curpeers->peers_fe->last_change = now.tv_sec;
1602 curpeers->peers_fe->id = strdup(args[1]);
1603 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001604 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001605 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1606 curpeers->peers_fe->timeout.connect = 5000;
1607 curpeers->peers_fe->accept = peer_accept;
1608 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001609 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1610 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001611
1612 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1613
Willy Tarreau902636f2013-03-10 19:44:48 +01001614 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1615 if (errmsg && *errmsg) {
1616 indent_msg(&errmsg, 2);
1617 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001618 }
1619 else
1620 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1621 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001622 err_code |= ERR_FATAL;
1623 goto out;
1624 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001625
1626 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1627 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1628 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1629 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1630 l->accept = session_accept;
1631 l->handler = process_session;
1632 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1633 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1634 global.maxsock += l->maxconn;
1635 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001636 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001637 else {
1638 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1639 file, linenum, args[0], args[1],
1640 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1641 err_code |= ERR_FATAL;
1642 goto out;
1643 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001644 }
1645 } /* neither "peer" nor "peers" */
1646 else if (*args[0] != 0) {
1647 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1648 err_code |= ERR_ALERT | ERR_FATAL;
1649 goto out;
1650 }
1651
1652out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001653 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001654 return err_code;
1655}
1656
Simon Horman69d29f92013-02-23 15:14:19 +09001657static int init_check(struct check *check, int type, const char * file, int linenum)
1658{
1659 check->type = type;
1660
1661 /* Allocate buffer for requests... */
1662 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1663 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1664 return ERR_ALERT | ERR_ABORT;
1665 }
1666 check->bi->size = global.tune.chksize;
1667
1668 /* Allocate buffer for responses... */
1669 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1670 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1671 return ERR_ALERT | ERR_ABORT;
1672 }
1673 check->bo->size = global.tune.chksize;
1674
1675 /* Allocate buffer for partial results... */
1676 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1677 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1678 return ERR_ALERT | ERR_ABORT;
1679 }
1680
1681 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1682
1683 return 0;
1684}
Emeric Brun32da3c42010-09-23 18:39:19 +02001685
Willy Tarreau3842f002009-06-14 11:39:52 +02001686int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001687{
1688 static struct proxy *curproxy = NULL;
1689 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001690 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001691 int rc;
1692 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001693 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001694 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001695 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001696 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001697 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 if (!strcmp(args[0], "listen"))
1700 rc = PR_CAP_LISTEN;
1701 else if (!strcmp(args[0], "frontend"))
1702 rc = PR_CAP_FE | PR_CAP_RS;
1703 else if (!strcmp(args[0], "backend"))
1704 rc = PR_CAP_BE | PR_CAP_RS;
1705 else if (!strcmp(args[0], "ruleset"))
1706 rc = PR_CAP_RS;
1707 else
1708 rc = PR_CAP_NONE;
1709
1710 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 if (!*args[1]) {
1712 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1713 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001715 err_code |= ERR_ALERT | ERR_ABORT;
1716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001718
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001719 err = invalid_char(args[1]);
1720 if (err) {
1721 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1722 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001723 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001724 }
1725
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001726 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1727 /*
1728 * If there are two proxies with the same name only following
1729 * combinations are allowed:
1730 *
1731 * listen backend frontend ruleset
1732 * listen - - - -
1733 * backend - - OK -
1734 * frontend - OK - -
1735 * ruleset - - - -
1736 */
1737
1738 if (!strcmp(curproxy->id, args[1]) &&
1739 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1740 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001741 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1742 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1743 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001744 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001745 }
1746 }
1747
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1749 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001750 err_code |= ERR_ALERT | ERR_ABORT;
1751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001753
Willy Tarreau97cb7802010-01-03 20:23:58 +01001754 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 curproxy->next = proxy;
1756 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001757 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1758 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001759 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001761 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762
1763 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001764 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001765 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001766
Willy Tarreau4348fad2012-09-20 16:48:07 +02001767 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1768
Willy Tarreau902636f2013-03-10 19:44:48 +01001769 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1770 if (errmsg && *errmsg) {
1771 indent_msg(&errmsg, 2);
1772 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001773 }
1774 else
1775 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1776 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001777 err_code |= ERR_FATAL;
1778 goto out;
1779 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001780
Willy Tarreau4348fad2012-09-20 16:48:07 +02001781 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001782 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001783 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784 }
1785
1786 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001787 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001788 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001789
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001792 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001793 curproxy->no_options = defproxy.no_options;
1794 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001795 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001796 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001797 curproxy->except_net = defproxy.except_net;
1798 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001799 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001800 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001802 if (defproxy.fwdfor_hdr_len) {
1803 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1804 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1805 }
1806
Willy Tarreaub86db342009-11-30 11:50:16 +01001807 if (defproxy.orgto_hdr_len) {
1808 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1809 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1810 }
1811
Mark Lamourinec2247f02012-01-04 13:02:01 -05001812 if (defproxy.server_id_hdr_len) {
1813 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1814 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1815 }
1816
Willy Tarreau977b8e42006-12-29 14:19:17 +01001817 if (curproxy->cap & PR_CAP_FE) {
1818 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001819 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001820 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001821
1822 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001823 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1824 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001825
1826 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828
Willy Tarreau977b8e42006-12-29 14:19:17 +01001829 if (curproxy->cap & PR_CAP_BE) {
1830 curproxy->fullconn = defproxy.fullconn;
1831 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001832
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001833 if (defproxy.check_req) {
1834 curproxy->check_req = calloc(1, defproxy.check_len);
1835 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1836 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001837 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001838
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001839 if (defproxy.expect_str) {
1840 curproxy->expect_str = strdup(defproxy.expect_str);
1841 if (defproxy.expect_regex) {
1842 /* note: this regex is known to be valid */
1843 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1844 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1845 }
1846 }
1847
Willy Tarreau67402132012-05-31 20:40:20 +02001848 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 if (defproxy.cookie_name)
1850 curproxy->cookie_name = strdup(defproxy.cookie_name);
1851 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001852 if (defproxy.cookie_domain)
1853 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001854
Willy Tarreau31936852010-10-06 16:59:56 +02001855 if (defproxy.cookie_maxidle)
1856 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1857
1858 if (defproxy.cookie_maxlife)
1859 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1860
Emeric Brun647caf12009-06-30 17:57:00 +02001861 if (defproxy.rdp_cookie_name)
1862 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1863 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1864
Willy Tarreau01732802007-11-01 22:48:15 +01001865 if (defproxy.url_param_name)
1866 curproxy->url_param_name = strdup(defproxy.url_param_name);
1867 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001868
Benoitaffb4812009-03-25 13:02:10 +01001869 if (defproxy.hh_name)
1870 curproxy->hh_name = strdup(defproxy.hh_name);
1871 curproxy->hh_len = defproxy.hh_len;
1872 curproxy->hh_match_domain = defproxy.hh_match_domain;
1873
Willy Tarreauef9a3602012-12-08 22:29:20 +01001874 if (defproxy.conn_src.iface_name)
1875 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1876 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001877 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001878#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001879 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001880#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001882
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001883 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001884 if (defproxy.capture_name)
1885 curproxy->capture_name = strdup(defproxy.capture_name);
1886 curproxy->capture_namelen = defproxy.capture_namelen;
1887 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001889
Willy Tarreau977b8e42006-12-29 14:19:17 +01001890 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001891 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001892 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001893 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001894 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001895 curproxy->uri_auth = defproxy.uri_auth;
1896 curproxy->mon_net = defproxy.mon_net;
1897 curproxy->mon_mask = defproxy.mon_mask;
1898 if (defproxy.monitor_uri)
1899 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1900 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001901 if (defproxy.defbe.name)
1902 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001903
1904 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001905 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1906 if (curproxy->conf.logformat_string &&
1907 curproxy->conf.logformat_string != default_http_log_format &&
1908 curproxy->conf.logformat_string != default_tcp_log_format &&
1909 curproxy->conf.logformat_string != clf_http_log_format)
1910 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1911
1912 if (defproxy.conf.lfs_file) {
1913 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1914 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1915 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 }
1917
1918 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001919 curproxy->timeout.connect = defproxy.timeout.connect;
1920 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001921 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001922 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001923 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001924 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001925 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001926 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001927 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 }
1929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001931
1932 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001933 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001934 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001935 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001936 LIST_INIT(&node->list);
1937 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1938 }
1939
Willy Tarreau62a61232013-04-12 18:13:46 +02001940 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1941 if (curproxy->conf.uniqueid_format_string)
1942 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1943
1944 if (defproxy.conf.uif_file) {
1945 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1946 curproxy->conf.uif_line = defproxy.conf.uif_line;
1947 }
William Lallemanda73203e2012-03-12 12:48:57 +01001948
1949 /* copy default header unique id */
1950 if (defproxy.header_unique_id)
1951 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1952
William Lallemand82fe75c2012-10-23 10:25:10 +02001953 /* default compression options */
1954 if (defproxy.comp != NULL) {
1955 curproxy->comp = calloc(1, sizeof(struct comp));
1956 curproxy->comp->algos = defproxy.comp->algos;
1957 curproxy->comp->types = defproxy.comp->types;
1958 }
1959
Willy Tarreaubaaee002006-06-26 02:48:02 +02001960 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001961 curproxy->conf.used_listener_id = EB_ROOT;
1962 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001963
Willy Tarreau93893792009-07-23 13:19:11 +02001964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 }
1966 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1967 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001968 /* FIXME-20070101: we should do this too at the end of the
1969 * config parsing to free all default values.
1970 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001971 free(defproxy.check_req);
1972 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001973 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001974 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001975 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001976 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001977 free(defproxy.capture_name);
1978 free(defproxy.monitor_uri);
1979 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001980 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001981 free(defproxy.fwdfor_hdr_name);
1982 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001983 free(defproxy.orgto_hdr_name);
1984 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001985 free(defproxy.server_id_hdr_name);
1986 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001987 free(defproxy.expect_str);
1988 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001989
Willy Tarreau62a61232013-04-12 18:13:46 +02001990 if (defproxy.conf.logformat_string != default_http_log_format &&
1991 defproxy.conf.logformat_string != default_tcp_log_format &&
1992 defproxy.conf.logformat_string != clf_http_log_format)
1993 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02001994
Willy Tarreau62a61232013-04-12 18:13:46 +02001995 free(defproxy.conf.uniqueid_format_string);
1996 free(defproxy.conf.lfs_file);
1997 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02001998
Willy Tarreaua534fea2008-08-03 12:19:50 +02001999 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002000 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002001
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 /* we cannot free uri_auth because it might already be used */
2003 init_default_instance();
2004 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002005 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2006 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002007 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002008 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002009 }
2010 else if (curproxy == NULL) {
2011 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002015
2016 /* update the current file and line being parsed */
2017 curproxy->conf.args.file = curproxy->conf.file;
2018 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002019
2020 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002022 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002023 int cur_arg;
2024
Willy Tarreaubaaee002006-06-26 02:48:02 +02002025 if (curproxy == &defproxy) {
2026 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002030 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002031 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002032
Willy Tarreau24709282013-03-10 21:32:12 +01002033 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002034 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002035 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002036 err_code |= ERR_ALERT | ERR_FATAL;
2037 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002039
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002040 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002041
2042 /* use default settings for unix sockets */
2043 bind_conf->ux.uid = global.unix_bind.ux.uid;
2044 bind_conf->ux.gid = global.unix_bind.ux.gid;
2045 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002046
2047 /* NOTE: the following line might create several listeners if there
2048 * are comma-separated IPs or port ranges. So all further processing
2049 * will have to be applied to all listeners created after last_listen.
2050 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002051 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2052 if (errmsg && *errmsg) {
2053 indent_msg(&errmsg, 2);
2054 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002055 }
2056 else
2057 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2058 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002059 err_code |= ERR_ALERT | ERR_FATAL;
2060 goto out;
2061 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002062
Willy Tarreau4348fad2012-09-20 16:48:07 +02002063 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2064 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002065 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002066 }
2067
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002068 cur_arg = 2;
2069 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002070 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002071 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002072 char *err;
2073
Willy Tarreau26982662012-09-12 23:17:10 +02002074 kw = bind_find_kw(args[cur_arg]);
2075 if (kw) {
2076 char *err = NULL;
2077 int code;
2078
2079 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002080 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2081 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002082 cur_arg += 1 + kw->skip ;
2083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
2085 }
2086
Willy Tarreau4348fad2012-09-20 16:48:07 +02002087 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002088 err_code |= code;
2089
2090 if (code) {
2091 if (err && *err) {
2092 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002093 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002094 }
2095 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002096 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2097 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002098 if (code & ERR_FATAL) {
2099 free(err);
2100 cur_arg += 1 + kw->skip;
2101 goto out;
2102 }
2103 }
2104 free(err);
2105 cur_arg += 1 + kw->skip;
2106 continue;
2107 }
2108
Willy Tarreau8638f482012-09-18 18:01:17 +02002109 err = NULL;
2110 if (!bind_dumped) {
2111 bind_dump_kws(&err);
2112 indent_msg(&err, 4);
2113 bind_dumped = 1;
2114 }
2115
2116 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2117 file, linenum, args[0], args[1], args[cur_arg],
2118 err ? " Registered keywords :" : "", err ? err : "");
2119 free(err);
2120
Willy Tarreau93893792009-07-23 13:19:11 +02002121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002123 }
Willy Tarreau93893792009-07-23 13:19:11 +02002124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002125 }
2126 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2127 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2128 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2129 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_ALERT | ERR_FATAL;
2131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002132 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002133 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002134 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002135
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 /* flush useless bits */
2137 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002139 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002140 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002141 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002143
Willy Tarreau1c47f852006-07-09 08:22:27 +02002144 if (!*args[1]) {
2145 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2146 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002149 }
2150
Willy Tarreaua534fea2008-08-03 12:19:50 +02002151 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002152 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002153 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002154 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002155 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2156
Willy Tarreau93893792009-07-23 13:19:11 +02002157 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002158 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002159 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2160 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2161 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2162 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2163 else {
2164 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002165 err_code |= ERR_ALERT | ERR_FATAL;
2166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002167 }
2168 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002169 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002170 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002171
2172 if (curproxy == &defproxy) {
2173 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002175 err_code |= ERR_ALERT | ERR_FATAL;
2176 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002177 }
2178
2179 if (!*args[1]) {
2180 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2181 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002182 err_code |= ERR_ALERT | ERR_FATAL;
2183 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002184 }
2185
2186 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002187 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002188
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002189 if (curproxy->uuid <= 0) {
2190 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002191 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002192 err_code |= ERR_ALERT | ERR_FATAL;
2193 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002194 }
2195
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002196 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2197 if (node) {
2198 struct proxy *target = container_of(node, struct proxy, conf.id);
2199 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2200 file, linenum, proxy_type_str(curproxy), curproxy->id,
2201 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
2204 }
2205 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002206 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002207 else if (!strcmp(args[0], "description")) {
2208 int i, len=0;
2209 char *d;
2210
Cyril Bonté99ed3272010-01-24 23:29:44 +01002211 if (curproxy == &defproxy) {
2212 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2213 file, linenum, args[0]);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
2216 }
2217
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002218 if (!*args[1]) {
2219 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2220 file, linenum, args[0]);
2221 return -1;
2222 }
2223
2224 for(i=1; *args[i]; i++)
2225 len += strlen(args[i])+1;
2226
2227 d = (char *)calloc(1, len);
2228 curproxy->desc = d;
2229
2230 d += sprintf(d, "%s", args[1]);
2231 for(i=2; *args[i]; i++)
2232 d += sprintf(d, " %s", args[i]);
2233
2234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002235 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2236 curproxy->state = PR_STSTOPPED;
2237 }
2238 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2239 curproxy->state = PR_STNEW;
2240 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002241 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2242 int cur_arg = 1;
2243 unsigned int set = 0;
2244
2245 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002246 unsigned int low, high;
2247
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002248 if (strcmp(args[cur_arg], "all") == 0) {
2249 set = 0;
2250 break;
2251 }
2252 else if (strcmp(args[cur_arg], "odd") == 0) {
2253 set |= 0x55555555;
2254 }
2255 else if (strcmp(args[cur_arg], "even") == 0) {
2256 set |= 0xAAAAAAAA;
2257 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002258 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002259 char *dash = strchr(args[cur_arg], '-');
2260
2261 low = high = str2uic(args[cur_arg]);
2262 if (dash)
2263 high = str2uic(dash + 1);
2264
2265 if (high < low) {
2266 unsigned int swap = low;
2267 low = high;
2268 high = swap;
2269 }
2270
2271 if (low < 1 || high > 32) {
2272 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002273 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_ALERT | ERR_FATAL;
2275 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002276 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002277
2278 if (high > global.nbproc) {
2279 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2280 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002282 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002283 while (low <= high)
2284 set |= 1 << (low++ - 1);
2285 }
2286 else {
2287 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2288 file, linenum, args[0]);
2289 err_code |= ERR_ALERT | ERR_FATAL;
2290 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002291 }
2292 cur_arg++;
2293 }
2294 curproxy->bind_proc = set;
2295 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002296 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002297 if (curproxy == &defproxy) {
2298 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002301 }
2302
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002303 err = invalid_char(args[1]);
2304 if (err) {
2305 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2306 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002307 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002308 }
2309
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002310 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002311 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2312 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_FATAL;
2314 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002315 }
2316 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2318 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319
Willy Tarreau977b8e42006-12-29 14:19:17 +01002320 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002321 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002322
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 if (*(args[1]) == 0) {
2324 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002329
Willy Tarreau67402132012-05-31 20:40:20 +02002330 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002331 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002332 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002333 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002334 curproxy->cookie_name = strdup(args[1]);
2335 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002336
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 cur_arg = 2;
2338 while (*(args[cur_arg])) {
2339 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002340 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341 }
2342 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002343 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 }
2345 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002346 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002347 }
2348 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002349 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 }
2351 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002352 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002354 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002355 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002356 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002358 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002360 else if (!strcmp(args[cur_arg], "httponly")) {
2361 curproxy->ck_opts |= PR_CK_HTTPONLY;
2362 }
2363 else if (!strcmp(args[cur_arg], "secure")) {
2364 curproxy->ck_opts |= PR_CK_SECURE;
2365 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002366 else if (!strcmp(args[cur_arg], "domain")) {
2367 if (!*args[cur_arg + 1]) {
2368 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2369 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002372 }
2373
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002374 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002375 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002376 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2377 " dots nor does not start with a dot."
2378 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002379 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002380 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002381 }
2382
2383 err = invalid_domainchar(args[cur_arg + 1]);
2384 if (err) {
2385 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2386 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002389 }
2390
Willy Tarreau68a897b2009-12-03 23:28:34 +01002391 if (!curproxy->cookie_domain) {
2392 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2393 } else {
2394 /* one domain was already specified, add another one by
2395 * building the string which will be returned along with
2396 * the cookie.
2397 */
2398 char *new_ptr;
2399 int new_len = strlen(curproxy->cookie_domain) +
2400 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2401 new_ptr = malloc(new_len);
2402 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2403 free(curproxy->cookie_domain);
2404 curproxy->cookie_domain = new_ptr;
2405 }
Willy Tarreau31936852010-10-06 16:59:56 +02002406 cur_arg++;
2407 }
2408 else if (!strcmp(args[cur_arg], "maxidle")) {
2409 unsigned int maxidle;
2410 const char *res;
2411
2412 if (!*args[cur_arg + 1]) {
2413 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2414 file, linenum, args[cur_arg]);
2415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
2417 }
2418
2419 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2420 if (res) {
2421 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2422 file, linenum, *res, args[cur_arg]);
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426 curproxy->cookie_maxidle = maxidle;
2427 cur_arg++;
2428 }
2429 else if (!strcmp(args[cur_arg], "maxlife")) {
2430 unsigned int maxlife;
2431 const char *res;
2432
2433 if (!*args[cur_arg + 1]) {
2434 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2435 file, linenum, args[cur_arg]);
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439
2440 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2441 if (res) {
2442 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2443 file, linenum, *res, args[cur_arg]);
2444 err_code |= ERR_ALERT | ERR_FATAL;
2445 goto out;
2446 }
2447 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002448 cur_arg++;
2449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002451 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 +02002452 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002453 err_code |= ERR_ALERT | ERR_FATAL;
2454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
2456 cur_arg++;
2457 }
Willy Tarreau67402132012-05-31 20:40:20 +02002458 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2460 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002461 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 }
2463
Willy Tarreau67402132012-05-31 20:40:20 +02002464 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2466 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002467 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002468 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002469
Willy Tarreau67402132012-05-31 20:40:20 +02002470 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002471 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2472 file, linenum);
2473 err_code |= ERR_ALERT | ERR_FATAL;
2474 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002476 else if (!strcmp(args[0], "persist")) { /* persist */
2477 if (*(args[1]) == 0) {
2478 Alert("parsing [%s:%d] : missing persist method.\n",
2479 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002482 }
2483
2484 if (!strncmp(args[1], "rdp-cookie", 10)) {
2485 curproxy->options2 |= PR_O2_RDPC_PRST;
2486
Emeric Brunb982a3d2010-01-04 15:45:53 +01002487 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002488 const char *beg, *end;
2489
2490 beg = args[1] + 11;
2491 end = strchr(beg, ')');
2492
2493 if (!end || end == beg) {
2494 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2495 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002496 err_code |= ERR_ALERT | ERR_FATAL;
2497 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002498 }
2499
2500 free(curproxy->rdp_cookie_name);
2501 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2502 curproxy->rdp_cookie_len = end-beg;
2503 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002504 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002505 free(curproxy->rdp_cookie_name);
2506 curproxy->rdp_cookie_name = strdup("msts");
2507 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2508 }
2509 else { /* syntax */
2510 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2511 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002514 }
2515 }
2516 else {
2517 Alert("parsing [%s:%d] : unknown persist method.\n",
2518 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002521 }
2522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002524 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002526 if (curproxy == &defproxy) {
2527 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
2530 }
2531
Willy Tarreau977b8e42006-12-29 14:19:17 +01002532 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002533 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002534
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002536 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
2539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 }
2541 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002542 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 curproxy->appsession_name = strdup(args[1]);
2544 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2545 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002546 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2547 if (err) {
2548 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2549 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002552 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002553 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002554
Willy Tarreau51041c72007-09-09 21:56:53 +02002555 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2556 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_ALERT | ERR_ABORT;
2558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002560
2561 cur_arg = 6;
2562 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002563 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2564 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002565 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002566 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002567 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002568 } else if (!strcmp(args[cur_arg], "prefix")) {
2569 curproxy->options2 |= PR_O2_AS_PFX;
2570 } else if (!strcmp(args[cur_arg], "mode")) {
2571 if (!*args[cur_arg + 1]) {
2572 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2573 file, linenum, args[0], args[cur_arg]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577
2578 cur_arg++;
2579 if (!strcmp(args[cur_arg], "query-string")) {
2580 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2581 curproxy->options2 |= PR_O2_AS_M_QS;
2582 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2583 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2584 curproxy->options2 |= PR_O2_AS_M_PP;
2585 } else {
2586 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
2589 }
2590 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002591 cur_arg++;
2592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 } /* Url App Session */
2594 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002595 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002597
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002599 if (curproxy == &defproxy) {
2600 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2601 err_code |= ERR_ALERT | ERR_FATAL;
2602 goto out;
2603 }
2604
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 if (*(args[4]) == 0) {
2606 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2607 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_ALERT | ERR_FATAL;
2609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002611 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 curproxy->capture_name = strdup(args[2]);
2613 curproxy->capture_namelen = strlen(curproxy->capture_name);
2614 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002615 curproxy->to_log |= LW_COOKIE;
2616 }
2617 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2618 struct cap_hdr *hdr;
2619
2620 if (curproxy == &defproxy) {
2621 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 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 }
2625
2626 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2627 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2628 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002629 err_code |= ERR_ALERT | ERR_FATAL;
2630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 }
2632
2633 hdr = calloc(sizeof(struct cap_hdr), 1);
2634 hdr->next = curproxy->req_cap;
2635 hdr->name = strdup(args[3]);
2636 hdr->namelen = strlen(args[3]);
2637 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002638 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002639 hdr->index = curproxy->nb_req_cap++;
2640 curproxy->req_cap = hdr;
2641 curproxy->to_log |= LW_REQHDR;
2642 }
2643 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2644 struct cap_hdr *hdr;
2645
2646 if (curproxy == &defproxy) {
2647 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 +02002648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002650 }
2651
2652 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2653 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2654 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002657 }
2658 hdr = calloc(sizeof(struct cap_hdr), 1);
2659 hdr->next = curproxy->rsp_cap;
2660 hdr->name = strdup(args[3]);
2661 hdr->namelen = strlen(args[3]);
2662 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002663 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002664 hdr->index = curproxy->nb_rsp_cap++;
2665 curproxy->rsp_cap = hdr;
2666 curproxy->to_log |= LW_RSPHDR;
2667 }
2668 else {
2669 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2670 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 }
2674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002675 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002676 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002677 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 if (*(args[1]) == 0) {
2680 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\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 }
2685 curproxy->conn_retries = atol(args[1]);
2686 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002687 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002688 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002689
2690 if (curproxy == &defproxy) {
2691 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
2694 }
2695
Willy Tarreau20b0de52012-12-24 15:45:22 +01002696 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2697 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2698 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2699 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002700 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002701 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2702 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 +01002703 file, linenum, args[0]);
2704 err_code |= ERR_WARN;
2705 }
2706
Willy Tarreauff011f22011-01-06 17:51:27 +01002707 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002708
Willy Tarreauff011f22011-01-06 17:51:27 +01002709 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002710 err_code |= ERR_ALERT | ERR_ABORT;
2711 goto out;
2712 }
2713
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002714 err_code |= warnif_cond_conflicts(rule->cond,
2715 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2716 file, linenum);
2717
Willy Tarreauff011f22011-01-06 17:51:27 +01002718 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002719 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002720 else if (!strcmp(args[0], "http-response")) { /* response access control */
2721 struct http_res_rule *rule;
2722
2723 if (curproxy == &defproxy) {
2724 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728
2729 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2730 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2731 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2732 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2733 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2734 file, linenum, args[0]);
2735 err_code |= ERR_WARN;
2736 }
2737
2738 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2739
2740 if (!rule) {
2741 err_code |= ERR_ALERT | ERR_ABORT;
2742 goto out;
2743 }
2744
2745 err_code |= warnif_cond_conflicts(rule->cond,
2746 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2747 file, linenum);
2748
2749 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2750 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002751 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2752 /* set the header name and length into the proxy structure */
2753 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2754 err_code |= ERR_WARN;
2755
2756 if (!*args[1]) {
2757 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2758 file, linenum, args[0]);
2759 err_code |= ERR_ALERT | ERR_FATAL;
2760 goto out;
2761 }
2762
2763 /* set the desired header name */
2764 free(curproxy->server_id_hdr_name);
2765 curproxy->server_id_hdr_name = strdup(args[1]);
2766 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2767 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002768 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002769 if (curproxy == &defproxy) {
2770 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002773 }
2774
Willy Tarreauef6494c2010-01-28 17:12:36 +01002775 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002776 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2777 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002778 err_code |= ERR_ALERT | ERR_FATAL;
2779 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002780 }
2781
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002782 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2783 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2784 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002787 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002788
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002789 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002790 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002791 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002792 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002793 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002794
Cyril Bonté99ed3272010-01-24 23:29:44 +01002795 if (curproxy == &defproxy) {
2796 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
2799 }
2800
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002801 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002802 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2803 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002806 }
2807
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002808 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002809 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002810 err_code |= warnif_cond_conflicts(rule->cond,
2811 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2812 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002813 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002814 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002815 struct switching_rule *rule;
2816
Willy Tarreaub099aca2008-10-12 17:26:37 +02002817 if (curproxy == &defproxy) {
2818 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002819 err_code |= ERR_ALERT | ERR_FATAL;
2820 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002821 }
2822
Willy Tarreau55ea7572007-06-17 19:56:27 +02002823 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002825
2826 if (*(args[1]) == 0) {
2827 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002828 err_code |= ERR_ALERT | ERR_FATAL;
2829 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002830 }
2831
Willy Tarreauef6494c2010-01-28 17:12:36 +01002832 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002833 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2834 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_ALERT | ERR_FATAL;
2836 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002837 }
2838
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002839 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2840 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2841 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002844 }
2845
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002846 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002847
Willy Tarreau55ea7572007-06-17 19:56:27 +02002848 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2849 rule->cond = cond;
2850 rule->be.name = strdup(args[1]);
2851 LIST_INIT(&rule->list);
2852 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2853 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002854 else if (strcmp(args[0], "use-server") == 0) {
2855 struct server_rule *rule;
2856
2857 if (curproxy == &defproxy) {
2858 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862
2863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2864 err_code |= ERR_WARN;
2865
2866 if (*(args[1]) == 0) {
2867 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
2870 }
2871
2872 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2873 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2874 file, linenum, args[0]);
2875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
2877 }
2878
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002879 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2880 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2881 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002882 err_code |= ERR_ALERT | ERR_FATAL;
2883 goto out;
2884 }
2885
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002886 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002887
2888 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2889 rule->cond = cond;
2890 rule->srv.name = strdup(args[1]);
2891 LIST_INIT(&rule->list);
2892 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2893 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2894 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002895 else if ((!strcmp(args[0], "force-persist")) ||
2896 (!strcmp(args[0], "ignore-persist"))) {
2897 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002898
2899 if (curproxy == &defproxy) {
2900 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
2903 }
2904
2905 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2906 err_code |= ERR_WARN;
2907
Willy Tarreauef6494c2010-01-28 17:12:36 +01002908 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002909 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2910 file, linenum, args[0]);
2911 err_code |= ERR_ALERT | ERR_FATAL;
2912 goto out;
2913 }
2914
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002915 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2916 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2917 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920 }
2921
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002922 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2923 * where force-persist is applied.
2924 */
2925 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002926
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002927 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002928 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002929 if (!strcmp(args[0], "force-persist")) {
2930 rule->type = PERSIST_TYPE_FORCE;
2931 } else {
2932 rule->type = PERSIST_TYPE_IGNORE;
2933 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002934 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002935 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002936 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002937 else if (!strcmp(args[0], "stick-table")) {
2938 int myidx = 1;
2939
Emeric Brun32da3c42010-09-23 18:39:19 +02002940 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002941 curproxy->table.type = (unsigned int)-1;
2942 while (*args[myidx]) {
2943 const char *err;
2944
2945 if (strcmp(args[myidx], "size") == 0) {
2946 myidx++;
2947 if (!*(args[myidx])) {
2948 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2949 file, linenum, args[myidx-1]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
2953 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2954 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2955 file, linenum, *err, args[myidx-1]);
2956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
2958 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002959 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002960 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002961 else if (strcmp(args[myidx], "peers") == 0) {
2962 myidx++;
Godbach50523162013-12-11 19:48:57 +08002963 if (!*(args[myidx])) {
2964 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2965 file, linenum, args[myidx-1]);
2966 err_code |= ERR_ALERT | ERR_FATAL;
2967 goto out;
2968 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002969 curproxy->table.peers.name = strdup(args[myidx++]);
2970 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002971 else if (strcmp(args[myidx], "expire") == 0) {
2972 myidx++;
2973 if (!*(args[myidx])) {
2974 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2975 file, linenum, args[myidx-1]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2980 if (err) {
2981 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2982 file, linenum, *err, args[myidx-1]);
2983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
2985 }
2986 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002987 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002988 }
2989 else if (strcmp(args[myidx], "nopurge") == 0) {
2990 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002991 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002992 }
2993 else if (strcmp(args[myidx], "type") == 0) {
2994 myidx++;
2995 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2996 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2997 file, linenum, args[myidx]);
2998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
3000 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003001 /* myidx already points to next arg */
3002 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003003 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003004 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003005 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003006
3007 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003008 nw = args[myidx];
3009 while (*nw) {
3010 /* the "store" keyword supports a comma-separated list */
3011 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003012 sa = NULL; /* store arg */
3013 while (*nw && *nw != ',') {
3014 if (*nw == '(') {
3015 *nw = 0;
3016 sa = ++nw;
3017 while (*nw != ')') {
3018 if (!*nw) {
3019 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3020 file, linenum, args[0], cw);
3021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024 nw++;
3025 }
3026 *nw = '\0';
3027 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003028 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003029 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003030 if (*nw)
3031 *nw++ = '\0';
3032 type = stktable_get_data_type(cw);
3033 if (type < 0) {
3034 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3035 file, linenum, args[0], cw);
3036 err_code |= ERR_ALERT | ERR_FATAL;
3037 goto out;
3038 }
Willy Tarreauac782882010-06-20 10:41:54 +02003039
3040 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3041 switch (err) {
3042 case PE_NONE: break;
3043 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003044 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3045 file, linenum, args[0], cw);
3046 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003047 break;
3048
3049 case PE_ARG_MISSING:
3050 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3051 file, linenum, args[0], cw);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054
3055 case PE_ARG_NOT_USED:
3056 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3057 file, linenum, args[0], cw);
3058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
3060
3061 default:
3062 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3063 file, linenum, args[0], cw);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003066 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003067 }
3068 myidx++;
3069 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003070 else {
3071 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3072 file, linenum, args[myidx]);
3073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003075 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003076 }
3077
3078 if (!curproxy->table.size) {
3079 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3080 file, linenum);
3081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
3083 }
3084
3085 if (curproxy->table.type == (unsigned int)-1) {
3086 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3087 file, linenum);
3088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
3090 }
3091 }
3092 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003093 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003094 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003095 int myidx = 0;
3096 const char *name = NULL;
3097 int flags;
3098
3099 if (curproxy == &defproxy) {
3100 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104
3105 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3106 err_code |= ERR_WARN;
3107 goto out;
3108 }
3109
3110 myidx++;
3111 if ((strcmp(args[myidx], "store") == 0) ||
3112 (strcmp(args[myidx], "store-request") == 0)) {
3113 myidx++;
3114 flags = STK_IS_STORE;
3115 }
3116 else if (strcmp(args[myidx], "store-response") == 0) {
3117 myidx++;
3118 flags = STK_IS_STORE | STK_ON_RSP;
3119 }
3120 else if (strcmp(args[myidx], "match") == 0) {
3121 myidx++;
3122 flags = STK_IS_MATCH;
3123 }
3124 else if (strcmp(args[myidx], "on") == 0) {
3125 myidx++;
3126 flags = STK_IS_MATCH | STK_IS_STORE;
3127 }
3128 else {
3129 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 goto out;
3132 }
3133
3134 if (*(args[myidx]) == 0) {
3135 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
3138 }
3139
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003140 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003141 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003142 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003143 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147
3148 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003149 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3150 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3151 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003152 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003153 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 goto out;
3155 }
3156 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003157 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3158 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3159 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003160 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003161 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003162 goto out;
3163 }
3164 }
3165
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003166 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003167 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003168
Emeric Brunb982a3d2010-01-04 15:45:53 +01003169 if (strcmp(args[myidx], "table") == 0) {
3170 myidx++;
3171 name = args[myidx++];
3172 }
3173
Willy Tarreauef6494c2010-01-28 17:12:36 +01003174 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003175 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3176 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3177 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003178 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003179 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003180 goto out;
3181 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003182 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003183 else if (*(args[myidx])) {
3184 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3185 file, linenum, args[0], args[myidx]);
3186 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003187 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003188 goto out;
3189 }
Emeric Brun97679e72010-09-23 17:56:44 +02003190 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003191 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003192 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003193 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003194
Emeric Brunb982a3d2010-01-04 15:45:53 +01003195 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3196 rule->cond = cond;
3197 rule->expr = expr;
3198 rule->flags = flags;
3199 rule->table.name = name ? strdup(name) : NULL;
3200 LIST_INIT(&rule->list);
3201 if (flags & STK_ON_RSP)
3202 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3203 else
3204 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003207 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003208 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003209
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3211 curproxy->uri_auth = NULL; /* we must detach from the default config */
3212
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003213 if (!*args[1]) {
3214 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003215 } else if (!strcmp(args[1], "admin")) {
3216 struct stats_admin_rule *rule;
3217
3218 if (curproxy == &defproxy) {
3219 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3220 err_code |= ERR_ALERT | ERR_FATAL;
3221 goto out;
3222 }
3223
3224 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3225 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3226 err_code |= ERR_ALERT | ERR_ABORT;
3227 goto out;
3228 }
3229
3230 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3231 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3232 file, linenum, args[0], args[1]);
3233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
3235 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003236 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3237 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3238 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
3241 }
3242
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003243 err_code |= warnif_cond_conflicts(cond,
3244 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3245 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003246
3247 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3248 rule->cond = cond;
3249 LIST_INIT(&rule->list);
3250 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 } else if (!strcmp(args[1], "uri")) {
3252 if (*(args[2]) == 0) {
3253 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3257 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003258 err_code |= ERR_ALERT | ERR_ABORT;
3259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
3261 } else if (!strcmp(args[1], "realm")) {
3262 if (*(args[2]) == 0) {
3263 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003264 err_code |= ERR_ALERT | ERR_FATAL;
3265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3267 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003268 err_code |= ERR_ALERT | ERR_ABORT;
3269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003271 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003272 unsigned interval;
3273
3274 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3275 if (err) {
3276 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3277 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003278 err_code |= ERR_ALERT | ERR_FATAL;
3279 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003280 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3281 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003282 err_code |= ERR_ALERT | ERR_ABORT;
3283 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003284 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003285 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003286 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003287
3288 if (curproxy == &defproxy) {
3289 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
3293
3294 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3295 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3296 err_code |= ERR_ALERT | ERR_ABORT;
3297 goto out;
3298 }
3299
Willy Tarreauff011f22011-01-06 17:51:27 +01003300 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3301 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003302 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3303 file, linenum, args[0]);
3304 err_code |= ERR_WARN;
3305 }
3306
Willy Tarreauff011f22011-01-06 17:51:27 +01003307 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003308
Willy Tarreauff011f22011-01-06 17:51:27 +01003309 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003310 err_code |= ERR_ALERT | ERR_ABORT;
3311 goto out;
3312 }
3313
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003314 err_code |= warnif_cond_conflicts(rule->cond,
3315 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3316 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003317 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003318
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 } else if (!strcmp(args[1], "auth")) {
3320 if (*(args[2]) == 0) {
3321 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3325 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003326 err_code |= ERR_ALERT | ERR_ABORT;
3327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 }
3329 } else if (!strcmp(args[1], "scope")) {
3330 if (*(args[2]) == 0) {
3331 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3335 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003336 err_code |= ERR_ALERT | ERR_ABORT;
3337 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 }
3339 } else if (!strcmp(args[1], "enable")) {
3340 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
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 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003345 } else if (!strcmp(args[1], "hide-version")) {
3346 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3347 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_ALERT | ERR_ABORT;
3349 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003350 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003351 } else if (!strcmp(args[1], "show-legends")) {
3352 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3353 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3354 err_code |= ERR_ALERT | ERR_ABORT;
3355 goto out;
3356 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003357 } else if (!strcmp(args[1], "show-node")) {
3358
3359 if (*args[2]) {
3360 int i;
3361 char c;
3362
3363 for (i=0; args[2][i]; i++) {
3364 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003365 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3366 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003367 break;
3368 }
3369
3370 if (!i || args[2][i]) {
3371 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3372 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3373 file, linenum, args[0], args[1]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377 }
3378
3379 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3380 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3381 err_code |= ERR_ALERT | ERR_ABORT;
3382 goto out;
3383 }
3384 } else if (!strcmp(args[1], "show-desc")) {
3385 char *desc = NULL;
3386
3387 if (*args[2]) {
3388 int i, len=0;
3389 char *d;
3390
3391 for(i=2; *args[i]; i++)
3392 len += strlen(args[i])+1;
3393
3394 desc = d = (char *)calloc(1, len);
3395
3396 d += sprintf(d, "%s", args[2]);
3397 for(i=3; *args[i]; i++)
3398 d += sprintf(d, " %s", args[i]);
3399 }
3400
3401 if (!*args[2] && !global.desc)
3402 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3403 file, linenum, args[1]);
3404 else {
3405 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3406 free(desc);
3407 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3408 err_code |= ERR_ALERT | ERR_ABORT;
3409 goto out;
3410 }
3411 free(desc);
3412 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003414stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003415 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 +01003416 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003419 }
3420 }
3421 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003422 int optnum;
3423
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003424 if (*(args[1]) == '\0') {
3425 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3426 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003429 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003430
3431 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3432 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003433 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3434 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3435 file, linenum, cfg_opts[optnum].name);
3436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
3438 }
Willy Tarreau93893792009-07-23 13:19:11 +02003439 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3440 err_code |= ERR_WARN;
3441 goto out;
3442 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003443
Willy Tarreau3842f002009-06-14 11:39:52 +02003444 curproxy->no_options &= ~cfg_opts[optnum].val;
3445 curproxy->options &= ~cfg_opts[optnum].val;
3446
3447 switch (kwm) {
3448 case KWM_STD:
3449 curproxy->options |= cfg_opts[optnum].val;
3450 break;
3451 case KWM_NO:
3452 curproxy->no_options |= cfg_opts[optnum].val;
3453 break;
3454 case KWM_DEF: /* already cleared */
3455 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003456 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003457
Willy Tarreau93893792009-07-23 13:19:11 +02003458 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003459 }
3460 }
3461
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003462 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3463 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003464 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3465 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3466 file, linenum, cfg_opts2[optnum].name);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
Willy Tarreau93893792009-07-23 13:19:11 +02003470 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3471 err_code |= ERR_WARN;
3472 goto out;
3473 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003474
Willy Tarreau3842f002009-06-14 11:39:52 +02003475 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3476 curproxy->options2 &= ~cfg_opts2[optnum].val;
3477
3478 switch (kwm) {
3479 case KWM_STD:
3480 curproxy->options2 |= cfg_opts2[optnum].val;
3481 break;
3482 case KWM_NO:
3483 curproxy->no_options2 |= cfg_opts2[optnum].val;
3484 break;
3485 case KWM_DEF: /* already cleared */
3486 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003487 }
Willy Tarreau93893792009-07-23 13:19:11 +02003488 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003489 }
3490 }
3491
Willy Tarreau3842f002009-06-14 11:39:52 +02003492 if (kwm != KWM_STD) {
3493 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003494 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003495 err_code |= ERR_ALERT | ERR_FATAL;
3496 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003497 }
3498
Emeric Brun3a058f32009-06-30 18:26:00 +02003499 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003500 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003501 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003502 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003503 if (*(args[2]) != '\0') {
3504 if (!strcmp(args[2], "clf")) {
3505 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003506 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003507 } else {
3508 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003511 }
3512 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003513 if (curproxy->conf.logformat_string != default_http_log_format &&
3514 curproxy->conf.logformat_string != default_tcp_log_format &&
3515 curproxy->conf.logformat_string != clf_http_log_format)
3516 free(curproxy->conf.logformat_string);
3517 curproxy->conf.logformat_string = logformat;
3518
3519 free(curproxy->conf.lfs_file);
3520 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3521 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003522 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003523 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003525 if (curproxy->conf.logformat_string != default_http_log_format &&
3526 curproxy->conf.logformat_string != default_tcp_log_format &&
3527 curproxy->conf.logformat_string != clf_http_log_format)
3528 free(curproxy->conf.logformat_string);
3529 curproxy->conf.logformat_string = default_tcp_log_format;
3530
3531 free(curproxy->conf.lfs_file);
3532 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3533 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 else if (!strcmp(args[1], "tcpka")) {
3536 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003537 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003539
3540 if (curproxy->cap & PR_CAP_FE)
3541 curproxy->options |= PR_O_TCP_CLI_KA;
3542 if (curproxy->cap & PR_CAP_BE)
3543 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 }
3545 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003546 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_WARN;
3548
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003550 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003551 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003552 curproxy->options2 &= ~PR_O2_CHK_ANY;
3553 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 if (!*args[2]) { /* no argument */
3555 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3556 curproxy->check_len = strlen(DEF_CHECK_REQ);
3557 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003558 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 curproxy->check_req = (char *)malloc(reqlen);
3560 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003561 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003563 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 if (*args[4])
3565 reqlen += strlen(args[4]);
3566 else
3567 reqlen += strlen("HTTP/1.0");
3568
3569 curproxy->check_req = (char *)malloc(reqlen);
3570 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003571 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003573 }
3574 else if (!strcmp(args[1], "ssl-hello-chk")) {
3575 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003576 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003577 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003578
Willy Tarreaua534fea2008-08-03 12:19:50 +02003579 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003580 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003581 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003582 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 }
Willy Tarreau23677902007-05-08 23:50:35 +02003584 else if (!strcmp(args[1], "smtpchk")) {
3585 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003586 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003587 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003588 curproxy->options2 &= ~PR_O2_CHK_ANY;
3589 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003590
3591 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3592 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3593 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3594 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3595 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3596 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3597 curproxy->check_req = (char *)malloc(reqlen);
3598 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3599 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3600 } else {
3601 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3602 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3603 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3604 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3605 }
3606 }
3607 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003608 else if (!strcmp(args[1], "pgsql-check")) {
3609 /* use PostgreSQL request to check servers' health */
3610 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3611 err_code |= ERR_WARN;
3612
3613 free(curproxy->check_req);
3614 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003615 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003616 curproxy->options2 |= PR_O2_PGSQL_CHK;
3617
3618 if (*(args[2])) {
3619 int cur_arg = 2;
3620
3621 while (*(args[cur_arg])) {
3622 if (strcmp(args[cur_arg], "user") == 0) {
3623 char * packet;
3624 uint32_t packet_len;
3625 uint32_t pv;
3626
3627 /* suboption header - needs additional argument for it */
3628 if (*(args[cur_arg+1]) == 0) {
3629 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3630 file, linenum, args[0], args[1], args[cur_arg]);
3631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
3633 }
3634
3635 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3636 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3637 pv = htonl(0x30000); /* protocol version 3.0 */
3638
3639 packet = (char*) calloc(1, packet_len);
3640
3641 memcpy(packet + 4, &pv, 4);
3642
3643 /* copy "user" */
3644 memcpy(packet + 8, "user", 4);
3645
3646 /* copy username */
3647 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3648
3649 free(curproxy->check_req);
3650 curproxy->check_req = packet;
3651 curproxy->check_len = packet_len;
3652
3653 packet_len = htonl(packet_len);
3654 memcpy(packet, &packet_len, 4);
3655 cur_arg += 2;
3656 } else {
3657 /* unknown suboption - catchall */
3658 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3659 file, linenum, args[0], args[1]);
3660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
3662 }
3663 } /* end while loop */
3664 }
3665 }
3666
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003667 else if (!strcmp(args[1], "redis-check")) {
3668 /* use REDIS PING request to check servers' health */
3669 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3670 err_code |= ERR_WARN;
3671
3672 free(curproxy->check_req);
3673 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003674 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003675 curproxy->options2 |= PR_O2_REDIS_CHK;
3676
3677 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3678 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3679 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3680 }
3681
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003682 else if (!strcmp(args[1], "mysql-check")) {
3683 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003684 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3685 err_code |= ERR_WARN;
3686
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003687 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003688 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003689 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003690 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003691
3692 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3693 * const char mysql40_client_auth_pkt[] = {
3694 * "\x0e\x00\x00" // packet length
3695 * "\x01" // packet number
3696 * "\x00\x00" // client capabilities
3697 * "\x00\x00\x01" // max packet
3698 * "haproxy\x00" // username (null terminated string)
3699 * "\x00" // filler (always 0x00)
3700 * "\x01\x00\x00" // packet length
3701 * "\x00" // packet number
3702 * "\x01" // COM_QUIT command
3703 * };
3704 */
3705
3706 if (*(args[2])) {
3707 int cur_arg = 2;
3708
3709 while (*(args[cur_arg])) {
3710 if (strcmp(args[cur_arg], "user") == 0) {
3711 char *mysqluser;
3712 int packetlen, reqlen, userlen;
3713
3714 /* suboption header - needs additional argument for it */
3715 if (*(args[cur_arg+1]) == 0) {
3716 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3717 file, linenum, args[0], args[1], args[cur_arg]);
3718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
3720 }
3721 mysqluser = args[cur_arg + 1];
3722 userlen = strlen(mysqluser);
3723 packetlen = userlen + 7;
3724 reqlen = packetlen + 9;
3725
3726 free(curproxy->check_req);
3727 curproxy->check_req = (char *)calloc(1, reqlen);
3728 curproxy->check_len = reqlen;
3729
3730 snprintf(curproxy->check_req, 4, "%c%c%c",
3731 ((unsigned char) packetlen & 0xff),
3732 ((unsigned char) (packetlen >> 8) & 0xff),
3733 ((unsigned char) (packetlen >> 16) & 0xff));
3734
3735 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003736 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003737 curproxy->check_req[8] = 1;
3738 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3739 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3740 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3741 cur_arg += 2;
3742 } else {
3743 /* unknown suboption - catchall */
3744 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3745 file, linenum, args[0], args[1]);
3746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
3748 }
3749 } /* end while loop */
3750 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003751 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003752 else if (!strcmp(args[1], "ldap-check")) {
3753 /* use LDAP request to check servers' health */
3754 free(curproxy->check_req);
3755 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003756 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003757 curproxy->options2 |= PR_O2_LDAP_CHK;
3758
3759 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3760 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3761 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3762 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003763 else if (!strcmp(args[1], "tcp-check")) {
3764 /* use raw TCPCHK send/expect to check servers' health */
3765 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3766 err_code |= ERR_WARN;
3767
3768 free(curproxy->check_req);
3769 curproxy->check_req = NULL;
3770 curproxy->options2 &= ~PR_O2_CHK_ANY;
3771 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3772 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003773 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003774 int cur_arg;
3775
3776 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3777 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003778 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003779
Willy Tarreau87cf5142011-08-19 22:57:24 +02003780 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003781
3782 free(curproxy->fwdfor_hdr_name);
3783 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3784 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3785
3786 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3787 cur_arg = 2;
3788 while (*(args[cur_arg])) {
3789 if (!strcmp(args[cur_arg], "except")) {
3790 /* suboption except - needs additional argument for it */
3791 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3792 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3793 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_FATAL;
3795 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003796 }
3797 /* flush useless bits */
3798 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003799 cur_arg += 2;
3800 } else if (!strcmp(args[cur_arg], "header")) {
3801 /* suboption header - needs additional argument for it */
3802 if (*(args[cur_arg+1]) == 0) {
3803 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3804 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003805 err_code |= ERR_ALERT | ERR_FATAL;
3806 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003807 }
3808 free(curproxy->fwdfor_hdr_name);
3809 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3810 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3811 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003812 } else if (!strcmp(args[cur_arg], "if-none")) {
3813 curproxy->options &= ~PR_O_FF_ALWAYS;
3814 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003815 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003816 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003817 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003818 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003819 err_code |= ERR_ALERT | ERR_FATAL;
3820 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003821 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003822 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003823 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003824 else if (!strcmp(args[1], "originalto")) {
3825 int cur_arg;
3826
3827 /* insert x-original-to field, but not for the IP address listed as an except.
3828 * set default options (ie: bitfield, header name, etc)
3829 */
3830
3831 curproxy->options |= PR_O_ORGTO;
3832
3833 free(curproxy->orgto_hdr_name);
3834 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3835 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3836
Willy Tarreau87cf5142011-08-19 22:57:24 +02003837 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003838 cur_arg = 2;
3839 while (*(args[cur_arg])) {
3840 if (!strcmp(args[cur_arg], "except")) {
3841 /* suboption except - needs additional argument for it */
3842 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3843 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3844 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003847 }
3848 /* flush useless bits */
3849 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3850 cur_arg += 2;
3851 } else if (!strcmp(args[cur_arg], "header")) {
3852 /* suboption header - needs additional argument for it */
3853 if (*(args[cur_arg+1]) == 0) {
3854 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3855 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003858 }
3859 free(curproxy->orgto_hdr_name);
3860 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3861 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3862 cur_arg += 2;
3863 } else {
3864 /* unknown suboption - catchall */
3865 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3866 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003869 }
3870 } /* end while loop */
3871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 else {
3873 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
Willy Tarreau93893792009-07-23 13:19:11 +02003877 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003879 else if (!strcmp(args[0], "default_backend")) {
3880 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003882
3883 if (*(args[1]) == 0) {
3884 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003887 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003888 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003889 curproxy->defbe.name = strdup(args[1]);
3890 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003892 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003894
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003895 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003898 /* enable reconnections to dispatch */
3899 curproxy->options |= PR_O_REDISP;
3900 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003901 else if (!strcmp(args[0], "http-check")) {
3902 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003903 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003904
3905 if (strcmp(args[1], "disable-on-404") == 0) {
3906 /* enable a graceful server shutdown on an HTTP 404 response */
3907 curproxy->options |= PR_O_DISABLE404;
3908 }
Willy Tarreauef781042010-01-27 11:53:01 +01003909 else if (strcmp(args[1], "send-state") == 0) {
3910 /* enable emission of the apparent state of a server in HTTP checks */
3911 curproxy->options2 |= PR_O2_CHK_SNDST;
3912 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003913 else if (strcmp(args[1], "expect") == 0) {
3914 const char *ptr_arg;
3915 int cur_arg;
3916
3917 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3918 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3919 err_code |= ERR_ALERT | ERR_FATAL;
3920 goto out;
3921 }
3922
3923 cur_arg = 2;
3924 /* consider exclamation marks, sole or at the beginning of a word */
3925 while (*(ptr_arg = args[cur_arg])) {
3926 while (*ptr_arg == '!') {
3927 curproxy->options2 ^= PR_O2_EXP_INV;
3928 ptr_arg++;
3929 }
3930 if (*ptr_arg)
3931 break;
3932 cur_arg++;
3933 }
3934 /* now ptr_arg points to the beginning of a word past any possible
3935 * exclamation mark, and cur_arg is the argument which holds this word.
3936 */
3937 if (strcmp(ptr_arg, "status") == 0) {
3938 if (!*(args[cur_arg + 1])) {
3939 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3940 file, linenum, args[0], args[1], ptr_arg);
3941 err_code |= ERR_ALERT | ERR_FATAL;
3942 goto out;
3943 }
3944 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003945 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003946 curproxy->expect_str = strdup(args[cur_arg + 1]);
3947 }
3948 else if (strcmp(ptr_arg, "string") == 0) {
3949 if (!*(args[cur_arg + 1])) {
3950 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3951 file, linenum, args[0], args[1], ptr_arg);
3952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
3954 }
3955 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003956 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003957 curproxy->expect_str = strdup(args[cur_arg + 1]);
3958 }
3959 else if (strcmp(ptr_arg, "rstatus") == 0) {
3960 if (!*(args[cur_arg + 1])) {
3961 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3962 file, linenum, args[0], args[1], ptr_arg);
3963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
3965 }
3966 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003967 free(curproxy->expect_str);
3968 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3969 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003970 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3971 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3972 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3973 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3974 err_code |= ERR_ALERT | ERR_FATAL;
3975 goto out;
3976 }
3977 }
3978 else if (strcmp(ptr_arg, "rstring") == 0) {
3979 if (!*(args[cur_arg + 1])) {
3980 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3981 file, linenum, args[0], args[1], ptr_arg);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984 }
3985 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003986 free(curproxy->expect_str);
3987 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3988 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003989 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3990 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3991 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3992 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
3996 }
3997 else {
3998 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3999 file, linenum, args[0], args[1], ptr_arg);
4000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
4002 }
4003 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004004 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004005 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 +02004006 err_code |= ERR_ALERT | ERR_FATAL;
4007 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004008 }
4009 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004010 else if (!strcmp(args[0], "tcp-check")) {
4011 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4012 err_code |= ERR_WARN;
4013
4014 if (strcmp(args[1], "send") == 0) {
4015 if (! *(args[2]) ) {
4016 /* SEND string expected */
4017 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4018 file, linenum, args[0], args[1], args[2]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 } else {
4022 struct tcpcheck_rule *tcpcheck;
4023
4024 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4025
4026 tcpcheck->action = TCPCHK_ACT_SEND;
4027 tcpcheck->string_len = strlen(args[2]);
4028 tcpcheck->string = strdup(args[2]);
4029 tcpcheck->expect_regex = NULL;
4030
4031 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4032 }
4033 }
4034 else if (strcmp(args[1], "send-binary") == 0) {
4035 if (! *(args[2]) ) {
4036 /* SEND binary string expected */
4037 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4038 file, linenum, args[0], args[1], args[2]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 } else {
4042 struct tcpcheck_rule *tcpcheck;
4043 char *err = NULL;
4044
4045 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4046
4047 tcpcheck->action = TCPCHK_ACT_SEND;
4048 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4049 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4050 file, linenum, args[0], args[1], args[2], err);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
4054 tcpcheck->expect_regex = NULL;
4055
4056 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4057 }
4058 }
4059 else if (strcmp(args[1], "expect") == 0) {
4060 const char *ptr_arg;
4061 int cur_arg;
4062 int inverse = 0;
4063
4064 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4065 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
4070 cur_arg = 2;
4071 /* consider exclamation marks, sole or at the beginning of a word */
4072 while (*(ptr_arg = args[cur_arg])) {
4073 while (*ptr_arg == '!') {
4074 inverse = !inverse;
4075 ptr_arg++;
4076 }
4077 if (*ptr_arg)
4078 break;
4079 cur_arg++;
4080 }
4081 /* now ptr_arg points to the beginning of a word past any possible
4082 * exclamation mark, and cur_arg is the argument which holds this word.
4083 */
4084 if (strcmp(ptr_arg, "binary") == 0) {
4085 if (!*(args[cur_arg + 1])) {
4086 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4087 file, linenum, args[0], args[1], ptr_arg);
4088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
4090 }
4091 struct tcpcheck_rule *tcpcheck;
4092 char *err = NULL;
4093
4094 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4095
4096 tcpcheck->action = TCPCHK_ACT_EXPECT;
4097 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4098 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4099 file, linenum, args[0], args[1], args[2], err);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103 tcpcheck->expect_regex = NULL;
4104 tcpcheck->inverse = inverse;
4105
4106 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4107 }
4108 else if (strcmp(ptr_arg, "string") == 0) {
4109 if (!*(args[cur_arg + 1])) {
4110 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4111 file, linenum, args[0], args[1], ptr_arg);
4112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
4114 }
4115 struct tcpcheck_rule *tcpcheck;
4116
4117 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4118
4119 tcpcheck->action = TCPCHK_ACT_EXPECT;
4120 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4121 tcpcheck->string = strdup(args[cur_arg + 1]);
4122 tcpcheck->expect_regex = NULL;
4123 tcpcheck->inverse = inverse;
4124
4125 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4126 }
4127 else if (strcmp(ptr_arg, "rstring") == 0) {
4128 if (!*(args[cur_arg + 1])) {
4129 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4130 file, linenum, args[0], args[1], ptr_arg);
4131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
4133 }
4134 struct tcpcheck_rule *tcpcheck;
4135
4136 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4137
4138 tcpcheck->action = TCPCHK_ACT_EXPECT;
4139 tcpcheck->string_len = 0;
4140 tcpcheck->string = NULL;
4141 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4142 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4143 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4144 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
4147 }
4148 tcpcheck->inverse = inverse;
4149
4150 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4151 }
4152 else {
4153 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4154 file, linenum, args[0], args[1], ptr_arg);
4155 err_code |= ERR_ALERT | ERR_FATAL;
4156 goto out;
4157 }
4158 }
4159 else {
4160 Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004165 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004166 if (curproxy == &defproxy) {
4167 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004170 }
4171
Willy Tarreaub80c2302007-11-30 20:51:32 +01004172 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004173 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004174
4175 if (strcmp(args[1], "fail") == 0) {
4176 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004177 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004178 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4179 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004180 err_code |= ERR_ALERT | ERR_FATAL;
4181 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004182 }
4183
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004184 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4185 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4186 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004187 err_code |= ERR_ALERT | ERR_FATAL;
4188 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004189 }
4190 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4191 }
4192 else {
4193 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004196 }
4197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004198#ifdef TPROXY
4199 else if (!strcmp(args[0], "transparent")) {
4200 /* enable transparent proxy connections */
4201 curproxy->options |= PR_O_TRANSP;
4202 }
4203#endif
4204 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004205 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004207
Willy Tarreaubaaee002006-06-26 02:48:02 +02004208 if (*(args[1]) == 0) {
4209 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 }
4213 curproxy->maxconn = atol(args[1]);
4214 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004215 else if (!strcmp(args[0], "backlog")) { /* backlog */
4216 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004217 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004218
4219 if (*(args[1]) == 0) {
4220 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004223 }
4224 curproxy->backlog = atol(args[1]);
4225 }
Willy Tarreau86034312006-12-29 00:10:33 +01004226 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004227 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004229
Willy Tarreau86034312006-12-29 00:10:33 +01004230 if (*(args[1]) == 0) {
4231 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004234 }
4235 curproxy->fullconn = atol(args[1]);
4236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004237 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4238 if (*(args[1]) == 0) {
4239 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004243 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4244 if (err) {
4245 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4246 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004249 }
4250 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 }
4252 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004253 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004254 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004255 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004256
Willy Tarreaubaaee002006-06-26 02:48:02 +02004257 if (curproxy == &defproxy) {
4258 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004262 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004264
Willy Tarreau902636f2013-03-10 19:44:48 +01004265 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004266 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004267 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004268 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004269 goto out;
4270 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004271
4272 proto = protocol_by_family(sk->ss_family);
4273 if (!proto || !proto->connect) {
4274 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4275 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
4278 }
4279
4280 if (port1 != port2) {
4281 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4282 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004286
4287 if (!port1) {
4288 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4289 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004290 err_code |= ERR_ALERT | ERR_FATAL;
4291 goto out;
4292 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004293
Willy Tarreaud5191e72010-02-09 20:50:45 +01004294 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004295 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004296 }
4297 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004298 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004300
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004301 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4302 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_ALERT | ERR_FATAL;
4304 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004305 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004306 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004307 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004308 /**
4309 * The syntax for hash-type config element is
4310 * hash-type {map-based|consistent} [[<algo>] avalanche]
4311 *
4312 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4313 */
4314 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004315
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004316 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4317 err_code |= ERR_WARN;
4318
4319 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004320 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4321 }
4322 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004323 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4324 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004325 else if (strcmp(args[1], "avalanche") == 0) {
4326 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]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004329 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004330 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004331 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
Bhaskar98634f02013-10-29 23:30:51 -04004335
4336 /* set the hash function to use */
4337 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004338 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004339 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004340
4341 /* if consistent with no argument, then avalanche modifier is also applied */
4342 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4343 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004344 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004345 /* set the hash function */
4346 if (!strcmp(args[2], "sdbm")) {
4347 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4348 }
4349 else if (!strcmp(args[2], "djb2")) {
4350 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004351 } else if (!strcmp(args[2], "wt6")) {
4352 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004353 }
4354 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004355 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 -05004356 err_code |= ERR_ALERT | ERR_FATAL;
4357 goto out;
4358 }
4359
4360 /* set the hash modifier */
4361 if (!strcmp(args[3], "avalanche")) {
4362 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4363 }
4364 else if (*args[3]) {
4365 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4366 err_code |= ERR_ALERT | ERR_FATAL;
4367 goto out;
4368 }
Bhaskar98634f02013-10-29 23:30:51 -04004369 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004370 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004371 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004372 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004373 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004374 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004375
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004376 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004380 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004381 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004383
4384 if (!*args[2]) {
4385 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4386 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004390
4391 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004392 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004393 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4394 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004397 }
4398
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004399 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004400 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004401 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004402 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004403
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004404 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4405 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4406 err_code |= ERR_ALERT | ERR_ABORT;
4407 goto out;
4408 }
4409
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004410 /* the servers are linked backwards first */
4411 newsrv->next = curproxy->srv;
4412 curproxy->srv = newsrv;
4413 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004414 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004415 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004417 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004418 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004419 LIST_INIT(&newsrv->pendconns);
4420 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004421 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004422 newsrv->state = SRV_RUNNING; /* early server setup */
4423 newsrv->last_change = now.tv_sec;
4424 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004425
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004426 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004427 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004428 * - IP: => port=+0, relative
4429 * - IP:N => port=N, absolute
4430 * - IP:+N => port=+N, relative
4431 * - IP:-N => port=-N, relative
4432 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004433 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004434 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004435 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004436 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004437 goto out;
4438 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004439
4440 proto = protocol_by_family(sk->ss_family);
4441 if (!proto || !proto->connect) {
4442 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4443 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
4446 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004447
4448 if (!port1 || !port2) {
4449 /* no port specified, +offset, -offset */
4450 newsrv->state |= SRV_MAPPORTS;
4451 }
4452 else if (port1 != port2) {
4453 /* port range */
4454 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4455 file, linenum, args[0], args[1], args[2]);
4456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
4458 }
4459 else {
4460 /* used by checks */
4461 realport = port1;
4462 }
4463
Willy Tarreaud5191e72010-02-09 20:50:45 +01004464 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004465 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4466 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004467
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004468 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004469 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4470 file, linenum, newsrv->addr.ss_family, args[2]);
4471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
4473 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004474
Simon Hormand60d6912013-11-25 10:46:36 +09004475 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004476 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004477 newsrv->check.inter = curproxy->defsrv.check.inter;
4478 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4479 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004480 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4481 newsrv->agent.port = curproxy->defsrv.agent.port;
4482 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4483 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4484 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004485 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4486 newsrv->minconn = curproxy->defsrv.minconn;
4487 newsrv->maxconn = curproxy->defsrv.maxconn;
4488 newsrv->slowstart = curproxy->defsrv.slowstart;
4489 newsrv->onerror = curproxy->defsrv.onerror;
4490 newsrv->consecutive_errors_limit
4491 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004492#ifdef OPENSSL
4493 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4494#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004495 newsrv->uweight = newsrv->iweight
4496 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004497
Simon Horman69d29f92013-02-23 15:14:19 +09004498 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004499 newsrv->check.rise = curproxy->defsrv.check.rise;
4500 newsrv->check.fall = curproxy->defsrv.check.fall;
4501 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004502 newsrv->check.server = newsrv;
4503
Simon Hormand60d6912013-11-25 10:46:36 +09004504 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004505 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4506 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4507 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004508 newsrv->agent.server = newsrv;
4509
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004510 cur_arg = 3;
4511 } else {
4512 newsrv = &curproxy->defsrv;
4513 cur_arg = 1;
4514 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004515
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004517 if (!strcmp(args[cur_arg], "agent-check")) {
4518 global.maxsock++;
4519 do_agent = 1;
4520 cur_arg += 1;
4521 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4522 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4523 if (err) {
4524 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4525 file, linenum, *err, newsrv->id);
4526 err_code |= ERR_ALERT | ERR_FATAL;
4527 goto out;
4528 }
4529 if (val <= 0) {
4530 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4531 file, linenum, val, args[cur_arg], newsrv->id);
4532 err_code |= ERR_ALERT | ERR_FATAL;
4533 goto out;
4534 }
4535 newsrv->agent.inter = val;
4536 cur_arg += 2;
4537 }
4538 else if (!strcmp(args[cur_arg], "agent-port")) {
4539 global.maxsock++;
4540 newsrv->agent.port = atol(args[cur_arg + 1]);
4541 cur_arg += 2;
4542 }
4543 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 newsrv->cookie = strdup(args[cur_arg + 1]);
4545 newsrv->cklen = strlen(args[cur_arg + 1]);
4546 cur_arg += 2;
4547 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004548 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004549 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4550 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4551 cur_arg += 2;
4552 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004553 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004554 if (!*args[cur_arg + 1]) {
4555 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4556 file, linenum, args[cur_arg]);
4557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
4559 }
4560
Simon Horman58c32972013-11-25 10:46:38 +09004561 newsrv->check.rise = atol(args[cur_arg + 1]);
4562 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004563 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4564 file, linenum, args[cur_arg]);
4565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
4568
Simon Horman125d0992013-02-24 17:23:38 +09004569 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004570 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004571 cur_arg += 2;
4572 }
4573 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004574 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004575
4576 if (!*args[cur_arg + 1]) {
4577 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4578 file, linenum, args[cur_arg]);
4579 err_code |= ERR_ALERT | ERR_FATAL;
4580 goto out;
4581 }
4582
Simon Horman58c32972013-11-25 10:46:38 +09004583 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004584 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4585 file, linenum, args[cur_arg]);
4586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
4588 }
4589
Willy Tarreaubaaee002006-06-26 02:48:02 +02004590 cur_arg += 2;
4591 }
4592 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004593 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4594 if (err) {
4595 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4596 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004599 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004600 if (val <= 0) {
4601 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4602 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004605 }
Simon Horman66183002013-02-23 10:16:43 +09004606 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 cur_arg += 2;
4608 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004609 else if (!strcmp(args[cur_arg], "fastinter")) {
4610 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4611 if (err) {
4612 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4613 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004616 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004617 if (val <= 0) {
4618 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4619 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004620 err_code |= ERR_ALERT | ERR_FATAL;
4621 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004622 }
Simon Horman66183002013-02-23 10:16:43 +09004623 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004624 cur_arg += 2;
4625 }
4626 else if (!strcmp(args[cur_arg], "downinter")) {
4627 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4628 if (err) {
4629 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4630 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004631 err_code |= ERR_ALERT | ERR_FATAL;
4632 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004633 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004634 if (val <= 0) {
4635 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4636 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004639 }
Simon Horman66183002013-02-23 10:16:43 +09004640 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004641 cur_arg += 2;
4642 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004643 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004644 struct sockaddr_storage *sk;
4645 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004646 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004647
Willy Tarreau902636f2013-03-10 19:44:48 +01004648 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004649 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004650 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004651 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004652 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004653 goto out;
4654 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004655
4656 proto = protocol_by_family(sk->ss_family);
4657 if (!proto || !proto->connect) {
4658 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004659 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004660 err_code |= ERR_ALERT | ERR_FATAL;
4661 goto out;
4662 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004663
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004664 if (port1 != port2) {
4665 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4666 file, linenum, args[cur_arg], args[cur_arg + 1]);
4667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669 }
4670
Simon Horman66183002013-02-23 10:16:43 +09004671 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004672 cur_arg += 2;
4673 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004674 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004675 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 cur_arg += 2;
4677 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004678 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 newsrv->state |= SRV_BACKUP;
4680 cur_arg ++;
4681 }
Simon Hormanfa461682011-06-25 09:39:49 +09004682 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4683 newsrv->state |= SRV_NON_STICK;
4684 cur_arg ++;
4685 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004686 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4687 newsrv->state |= SRV_SEND_PROXY;
4688 cur_arg ++;
4689 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004690 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4691 newsrv->check.send_proxy = 1;
4692 cur_arg ++;
4693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004694 else if (!strcmp(args[cur_arg], "weight")) {
4695 int w;
4696 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004697 if (w < 0 || w > SRV_UWGHT_MAX) {
4698 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4699 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004700 err_code |= ERR_ALERT | ERR_FATAL;
4701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004702 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004703 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 cur_arg += 2;
4705 }
4706 else if (!strcmp(args[cur_arg], "minconn")) {
4707 newsrv->minconn = atol(args[cur_arg + 1]);
4708 cur_arg += 2;
4709 }
4710 else if (!strcmp(args[cur_arg], "maxconn")) {
4711 newsrv->maxconn = atol(args[cur_arg + 1]);
4712 cur_arg += 2;
4713 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004714 else if (!strcmp(args[cur_arg], "maxqueue")) {
4715 newsrv->maxqueue = atol(args[cur_arg + 1]);
4716 cur_arg += 2;
4717 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004718 else if (!strcmp(args[cur_arg], "slowstart")) {
4719 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004720 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004721 if (err) {
4722 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4723 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004724 err_code |= ERR_ALERT | ERR_FATAL;
4725 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004726 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004727 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004728 cur_arg += 2;
4729 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004730 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004731
4732 if (!*args[cur_arg + 1]) {
4733 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4734 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004737 }
4738
4739 newsrv->trackit = strdup(args[cur_arg + 1]);
4740
4741 cur_arg += 2;
4742 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004743 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 global.maxsock++;
4745 do_check = 1;
4746 cur_arg += 1;
4747 }
Willy Tarreau96839092010-03-29 10:02:24 +02004748 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4749 newsrv->state |= SRV_MAINTAIN;
4750 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004751 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004752 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004753 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004754 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004755 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004756 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004757 if (!strcmp(args[cur_arg + 1], "none"))
4758 newsrv->observe = HANA_OBS_NONE;
4759 else if (!strcmp(args[cur_arg + 1], "layer4"))
4760 newsrv->observe = HANA_OBS_LAYER4;
4761 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4762 if (curproxy->mode != PR_MODE_HTTP) {
4763 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4764 file, linenum, args[cur_arg + 1]);
4765 err_code |= ERR_ALERT;
4766 }
4767 newsrv->observe = HANA_OBS_LAYER7;
4768 }
4769 else {
4770 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004771 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004772 file, linenum, args[cur_arg], args[cur_arg + 1]);
4773 err_code |= ERR_ALERT | ERR_FATAL;
4774 goto out;
4775 }
4776
4777 cur_arg += 2;
4778 }
4779 else if (!strcmp(args[cur_arg], "on-error")) {
4780 if (!strcmp(args[cur_arg + 1], "fastinter"))
4781 newsrv->onerror = HANA_ONERR_FASTINTER;
4782 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4783 newsrv->onerror = HANA_ONERR_FAILCHK;
4784 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4785 newsrv->onerror = HANA_ONERR_SUDDTH;
4786 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4787 newsrv->onerror = HANA_ONERR_MARKDWN;
4788 else {
4789 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004790 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004791 file, linenum, args[cur_arg], args[cur_arg + 1]);
4792 err_code |= ERR_ALERT | ERR_FATAL;
4793 goto out;
4794 }
4795
4796 cur_arg += 2;
4797 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004798 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4799 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4800 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4801 else {
4802 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4803 file, linenum, args[cur_arg], args[cur_arg + 1]);
4804 err_code |= ERR_ALERT | ERR_FATAL;
4805 goto out;
4806 }
4807
4808 cur_arg += 2;
4809 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004810 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4811 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4812 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4813 else {
4814 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4815 file, linenum, args[cur_arg], args[cur_arg + 1]);
4816 err_code |= ERR_ALERT | ERR_FATAL;
4817 goto out;
4818 }
4819
4820 cur_arg += 2;
4821 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004822 else if (!strcmp(args[cur_arg], "error-limit")) {
4823 if (!*args[cur_arg + 1]) {
4824 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4825 file, linenum, args[cur_arg]);
4826 err_code |= ERR_ALERT | ERR_FATAL;
4827 goto out;
4828 }
4829
4830 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4831
4832 if (newsrv->consecutive_errors_limit <= 0) {
4833 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4834 file, linenum, args[cur_arg]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004838 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004839 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004840 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004841 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004842 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004843 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004844
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004846 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4847 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004848 err_code |= ERR_ALERT | ERR_FATAL;
4849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004851
Willy Tarreauef9a3602012-12-08 22:29:20 +01004852 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004853 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004854 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004855 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004856 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004857 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004858 goto out;
4859 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +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",
4864 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 Tarreau2de5dae2013-03-10 18:51:54 +01004868
Willy Tarreauef9a3602012-12-08 22:29:20 +01004869 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004870
4871 if (port_low != port_high) {
4872 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004873
4874 if (!port_low || !port_high) {
4875 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4876 file, linenum, args[cur_arg], args[cur_arg + 1]);
4877 err_code |= ERR_ALERT | ERR_FATAL;
4878 goto out;
4879 }
4880
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004881 if (port_low <= 0 || port_low > 65535 ||
4882 port_high <= 0 || port_high > 65535 ||
4883 port_low > port_high) {
4884 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4885 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004888 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004889 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4890 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4891 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004892 }
4893
Willy Tarreaubaaee002006-06-26 02:48:02 +02004894 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004895 while (*(args[cur_arg])) {
4896 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004897#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4898#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004899 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004900 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4901 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004902 err_code |= ERR_ALERT | ERR_FATAL;
4903 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004904 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004905#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004906 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004907 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004908 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004911 }
4912 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004913 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4914 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004915 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004916 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4917 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004918 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4919 char *name, *end;
4920
4921 name = args[cur_arg+1] + 7;
4922 while (isspace(*name))
4923 name++;
4924
4925 end = name;
4926 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4927 end++;
4928
Willy Tarreauef9a3602012-12-08 22:29:20 +01004929 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4930 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
4931 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
4932 newsrv->conn_src.bind_hdr_len = end - name;
4933 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
4934 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
4935 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02004936
4937 /* now look for an occurrence number */
4938 while (isspace(*end))
4939 end++;
4940 if (*end == ',') {
4941 end++;
4942 name = end;
4943 if (*end == '-')
4944 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01004945 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02004946 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01004947 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02004948 }
4949
Willy Tarreauef9a3602012-12-08 22:29:20 +01004950 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004951 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4952 " occurrences values smaller than %d.\n",
4953 file, linenum, MAX_HDR_HISTORY);
4954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
4956 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004957 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004958 struct sockaddr_storage *sk;
4959 int port1, port2;
4960
Willy Tarreau902636f2013-03-10 19:44:48 +01004961 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004962 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004963 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004964 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004965 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004966 goto out;
4967 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004968
4969 proto = protocol_by_family(sk->ss_family);
4970 if (!proto || !proto->connect) {
4971 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4972 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
4975 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004976
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004977 if (port1 != port2) {
4978 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4979 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
4982 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004983 newsrv->conn_src.tproxy_addr = *sk;
4984 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004985 }
4986 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004987#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004988 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004989#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004990 cur_arg += 2;
4991 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004992#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004993 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004994 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02004997#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004998 } /* "usesrc" */
4999
5000 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5001#ifdef SO_BINDTODEVICE
5002 if (!*args[cur_arg + 1]) {
5003 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5004 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005005 err_code |= ERR_ALERT | ERR_FATAL;
5006 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005007 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005008 free(newsrv->conn_src.iface_name);
5009 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5010 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005011 global.last_checks |= LSTCHK_NETADM;
5012#else
5013 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5014 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_ALERT | ERR_FATAL;
5016 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005017#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005018 cur_arg += 2;
5019 continue;
5020 }
5021 /* this keyword in not an option of "source" */
5022 break;
5023 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005025 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005026 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5027 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005031 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005032 static int srv_dumped;
5033 struct srv_kw *kw;
5034 char *err;
5035
5036 kw = srv_find_kw(args[cur_arg]);
5037 if (kw) {
5038 char *err = NULL;
5039 int code;
5040
5041 if (!kw->parse) {
5042 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5043 file, linenum, args[0], args[1], args[cur_arg]);
5044 cur_arg += 1 + kw->skip ;
5045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
5047 }
5048
5049 if (defsrv && !kw->default_ok) {
5050 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5051 file, linenum, args[0], args[1], args[cur_arg]);
5052 cur_arg += 1 + kw->skip ;
5053 err_code |= ERR_ALERT;
5054 continue;
5055 }
5056
5057 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5058 err_code |= code;
5059
5060 if (code) {
5061 if (err && *err) {
5062 indent_msg(&err, 2);
5063 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5064 }
5065 else
5066 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5067 file, linenum, args[0], args[1], args[cur_arg]);
5068 if (code & ERR_FATAL) {
5069 free(err);
5070 cur_arg += 1 + kw->skip;
5071 goto out;
5072 }
5073 }
5074 free(err);
5075 cur_arg += 1 + kw->skip;
5076 continue;
5077 }
5078
5079 err = NULL;
5080 if (!srv_dumped) {
5081 srv_dump_kws(&err);
5082 indent_msg(&err, 4);
5083 srv_dumped = 1;
5084 }
5085
5086 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5087 file, linenum, args[0], args[1], args[cur_arg],
5088 err ? " Registered keywords :" : "", err ? err : "");
5089 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005090
Willy Tarreau93893792009-07-23 13:19:11 +02005091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093 }
5094 }
5095
Simon Horman8c3d0be2013-11-25 10:46:40 +09005096 /* Set initial drain state using now-configured weight */
5097 set_server_drain_state(newsrv);
5098
Willy Tarreaubaaee002006-06-26 02:48:02 +02005099 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005100 int ret;
5101
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005102 if (newsrv->trackit) {
5103 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5104 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005105 err_code |= ERR_ALERT | ERR_FATAL;
5106 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005107 }
5108
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005109 /* If neither a port nor an addr was specified and no check transport
5110 * layer is forced, then the transport layer used by the checks is the
5111 * same as for the production traffic. Otherwise we use raw_sock by
5112 * default, unless one is specified.
5113 */
Simon Horman66183002013-02-23 10:16:43 +09005114 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005115#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005116 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02005117#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005118 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5119 }
Simon Horman66183002013-02-23 10:16:43 +09005120 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005121 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005122 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005123
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005124 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005125 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005126
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005127 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005128 /* not yet valid, because no port was set on
5129 * the server either. We'll check if we have
5130 * a known port on the first listener.
5131 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005132 struct listener *l;
5133
5134 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005135 newsrv->check.port = get_host_port(&l->addr);
5136 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005137 break;
5138 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005139 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005140 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5142 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005145 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005146
Willy Tarreau2f075e92013-12-03 11:11:34 +01005147 /* note: check type will be set during the config review phase */
5148 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005149 if (ret) {
5150 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005151 goto out;
5152 }
5153
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005154 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 }
5156
Simon Hormand60d6912013-11-25 10:46:36 +09005157 if (do_agent) {
5158 int ret;
5159
5160 if (!newsrv->agent.port) {
5161 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5162 file, linenum, newsrv->id);
5163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
5165 }
5166
5167 if (!newsrv->agent.inter)
5168 newsrv->agent.inter = newsrv->check.inter;
5169
5170 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5171 if (ret) {
5172 err_code |= ret;
5173 goto out;
5174 }
5175
Willy Tarreau33434322013-12-11 21:15:19 +01005176 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005177 }
5178
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005179 if (!defsrv) {
5180 if (newsrv->state & SRV_BACKUP)
5181 curproxy->srv_bck++;
5182 else
5183 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005184
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005185 newsrv->prev_state = newsrv->state;
5186 }
William Lallemanda73203e2012-03-12 12:48:57 +01005187 }
5188
5189 else if (strcmp(args[0], "unique-id-format") == 0) {
5190 if (!*(args[1])) {
5191 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5192 err_code |= ERR_ALERT | ERR_FATAL;
5193 goto out;
5194 }
William Lallemand3203ff42012-11-11 17:30:56 +01005195 if (*(args[2])) {
5196 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5197 err_code |= ERR_ALERT | ERR_FATAL;
5198 goto out;
5199 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005200 free(curproxy->conf.uniqueid_format_string);
5201 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005202
Willy Tarreau62a61232013-04-12 18:13:46 +02005203 free(curproxy->conf.uif_file);
5204 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5205 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005206 }
William Lallemanda73203e2012-03-12 12:48:57 +01005207
5208 else if (strcmp(args[0], "unique-id-header") == 0) {
5209 if (!*(args[1])) {
5210 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5211 err_code |= ERR_ALERT | ERR_FATAL;
5212 goto out;
5213 }
5214 free(curproxy->header_unique_id);
5215 curproxy->header_unique_id = strdup(args[1]);
5216 }
5217
William Lallemand723b73a2012-02-08 16:37:49 +01005218 else if (strcmp(args[0], "log-format") == 0) {
5219 if (!*(args[1])) {
5220 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
5223 }
William Lallemand3203ff42012-11-11 17:30:56 +01005224 if (*(args[2])) {
5225 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5226 err_code |= ERR_ALERT | ERR_FATAL;
5227 goto out;
5228 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005229
Willy Tarreau62a61232013-04-12 18:13:46 +02005230 if (curproxy->conf.logformat_string != default_http_log_format &&
5231 curproxy->conf.logformat_string != default_tcp_log_format &&
5232 curproxy->conf.logformat_string != clf_http_log_format)
5233 free(curproxy->conf.logformat_string);
5234 curproxy->conf.logformat_string = strdup(args[1]);
5235
5236 free(curproxy->conf.lfs_file);
5237 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5238 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005239
5240 /* get a chance to improve log-format error reporting by
5241 * reporting the correct line-number when possible.
5242 */
5243 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5244 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5245 file, linenum, curproxy->id);
5246 err_code |= ERR_WARN;
5247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005248 }
William Lallemand723b73a2012-02-08 16:37:49 +01005249
William Lallemand0f99e342011-10-12 17:50:54 +02005250 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5251 /* delete previous herited or defined syslog servers */
5252 struct logsrv *back;
5253
5254 if (*(args[1]) != 0) {
5255 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5256 err_code |= ERR_ALERT | ERR_FATAL;
5257 goto out;
5258 }
5259
William Lallemand723b73a2012-02-08 16:37:49 +01005260 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5261 LIST_DEL(&tmplogsrv->list);
5262 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005263 }
5264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005266 struct logsrv *logsrv;
5267
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005269 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005270 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005271 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005272 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005273 LIST_INIT(&node->list);
5274 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005276 }
5277 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005278 struct sockaddr_storage *sk;
5279 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005280
5281 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005282
William Lallemand0f99e342011-10-12 17:50:54 +02005283 logsrv->facility = get_log_facility(args[2]);
5284 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
5288
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
5290
William Lallemand0f99e342011-10-12 17:50:54 +02005291 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005293 logsrv->level = get_log_level(args[3]);
5294 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005296 err_code |= ERR_ALERT | ERR_FATAL;
5297 goto out;
5298
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
5300 }
5301
William Lallemand0f99e342011-10-12 17:50:54 +02005302 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005303 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005304 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005305 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005306 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005307 err_code |= ERR_ALERT | ERR_FATAL;
5308 goto out;
5309
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005310 }
5311 }
5312
Willy Tarreau902636f2013-03-10 19:44:48 +01005313 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005314 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005315 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005316 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005317 goto out;
5318 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005319
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005320 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005321
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005322 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005323 if (port1 != port2) {
5324 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5325 file, linenum, args[0], args[1]);
5326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 }
5329
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005330 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005331 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 }
William Lallemand0f99e342011-10-12 17:50:54 +02005333
5334 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 }
5336 else {
5337 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5338 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005339 err_code |= ERR_ALERT | ERR_FATAL;
5340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
5342 }
5343 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005344 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005345 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005346 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005347 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005348
Willy Tarreau977b8e42006-12-29 14:19:17 +01005349 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005350 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005351
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005353 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5354 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005355 err_code |= ERR_ALERT | ERR_FATAL;
5356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005357 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005358
5359 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005360 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5361 free(curproxy->conn_src.iface_name);
5362 curproxy->conn_src.iface_name = NULL;
5363 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005364
Willy Tarreau902636f2013-03-10 19:44:48 +01005365 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005366 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005367 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005368 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005369 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005370 goto out;
5371 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005372
5373 proto = protocol_by_family(sk->ss_family);
5374 if (!proto || !proto->connect) {
5375 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005376 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
5379 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005380
5381 if (port1 != port2) {
5382 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5383 file, linenum, args[0], args[1]);
5384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
5386 }
5387
Willy Tarreauef9a3602012-12-08 22:29:20 +01005388 curproxy->conn_src.source_addr = *sk;
5389 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005390
5391 cur_arg = 2;
5392 while (*(args[cur_arg])) {
5393 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005394#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5395#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005396 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005397 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5398 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005401 }
5402#endif
5403 if (!*args[cur_arg + 1]) {
5404 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5405 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005408 }
5409
5410 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005411 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5412 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005413 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005414 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5415 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005416 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5417 char *name, *end;
5418
5419 name = args[cur_arg+1] + 7;
5420 while (isspace(*name))
5421 name++;
5422
5423 end = name;
5424 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5425 end++;
5426
Willy Tarreauef9a3602012-12-08 22:29:20 +01005427 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5428 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5429 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5430 curproxy->conn_src.bind_hdr_len = end - name;
5431 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5432 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5433 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005434
5435 /* now look for an occurrence number */
5436 while (isspace(*end))
5437 end++;
5438 if (*end == ',') {
5439 end++;
5440 name = end;
5441 if (*end == '-')
5442 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005443 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005444 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005445 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005446 }
5447
Willy Tarreauef9a3602012-12-08 22:29:20 +01005448 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005449 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5450 " occurrences values smaller than %d.\n",
5451 file, linenum, MAX_HDR_HISTORY);
5452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
5454 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005455 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005456 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005457
Willy Tarreau902636f2013-03-10 19:44:48 +01005458 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005459 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005460 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005461 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005462 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005463 goto out;
5464 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005465
5466 proto = protocol_by_family(sk->ss_family);
5467 if (!proto || !proto->connect) {
5468 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5469 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
5472 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005473
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005474 if (port1 != port2) {
5475 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5476 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005480 curproxy->conn_src.tproxy_addr = *sk;
5481 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005482 }
5483 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005484#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005485 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005486#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005487#else /* no TPROXY support */
5488 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005489 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005490 err_code |= ERR_ALERT | ERR_FATAL;
5491 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005492#endif
5493 cur_arg += 2;
5494 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005495 }
5496
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005497 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5498#ifdef SO_BINDTODEVICE
5499 if (!*args[cur_arg + 1]) {
5500 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5501 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005504 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005505 free(curproxy->conn_src.iface_name);
5506 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5507 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005508 global.last_checks |= LSTCHK_NETADM;
5509#else
5510 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5511 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005514#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005515 cur_arg += 2;
5516 continue;
5517 }
5518 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005519 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005520 err_code |= ERR_ALERT | ERR_FATAL;
5521 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005524 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5525 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5526 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005531 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5533 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005537
5538 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005539 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005540 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005541 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 }
5544 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005545 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005546 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005547 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005548 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 }
5551 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005552 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005553 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005554 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005555 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 }
5558 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005559 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005560 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005561 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005562 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 }
5565 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005566 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005567 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005568 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005569 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005571 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005572 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005573 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005574 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005575 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005576 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005577 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005578 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005579 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005580 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005581 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005582 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005583 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005584 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005585 }
5586 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005587 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005588 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005589 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005590 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005591 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005593 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005594 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5596 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005600
5601 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005602 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005603 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005604 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005605 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 }
5607 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005608 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005609 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005610 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005611 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005613 }
5614 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005615 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005616 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005617 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005618 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 }
5621 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005622 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005623 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005624 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005625 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 }
5628 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005629 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005630 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005631 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005632 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005635 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005636 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005637 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005638 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005639 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005640 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005642 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005643 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005644
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 if (curproxy == &defproxy) {
5646 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005650 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005651 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 if (*(args[1]) == 0) {
5654 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005657 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005658
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005659 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005660 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5661 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5662 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005663 err_code |= ERR_ALERT | ERR_FATAL;
5664 goto out;
5665 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005666 err_code |= warnif_cond_conflicts(cond,
5667 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5668 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005669 }
5670 else if (*args[2]) {
5671 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5672 file, linenum, args[0], args[2]);
5673 err_code |= ERR_ALERT | ERR_FATAL;
5674 goto out;
5675 }
5676
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005677 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005678 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005679 wl->s = strdup(args[1]);
5680 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005681 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005682 }
5683 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005684 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005685 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5686 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005687 err_code |= ERR_ALERT | ERR_FATAL;
5688 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005689 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005690
Willy Tarreauade5ec42010-01-28 19:33:49 +01005691 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005692 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005693 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005694 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005696 }
5697 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005698 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005699 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005700 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005701 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005702 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005703 }
5704 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005705 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005706 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005707 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005708 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005709 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005710 }
5711 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005712 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005713 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5714 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005717 }
5718
Willy Tarreauade5ec42010-01-28 19:33:49 +01005719 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005720 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005721 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005722 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005723 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 }
5725 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005726 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005727 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005728 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005729 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 }
5732 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005733 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005734 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005735 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005736 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 }
5739 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005740 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005741
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742 if (curproxy == &defproxy) {
5743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005744 err_code |= ERR_ALERT | ERR_FATAL;
5745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005747 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005748 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749
Willy Tarreaubaaee002006-06-26 02:48:02 +02005750 if (*(args[1]) == 0) {
5751 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005752 err_code |= ERR_ALERT | ERR_FATAL;
5753 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 }
5755
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005756 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005757 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5758 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5759 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005760 err_code |= ERR_ALERT | ERR_FATAL;
5761 goto out;
5762 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005763 err_code |= warnif_cond_conflicts(cond,
5764 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5765 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005766 }
5767 else if (*args[2]) {
5768 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5769 file, linenum, args[0], args[2]);
5770 err_code |= ERR_ALERT | ERR_FATAL;
5771 goto out;
5772 }
5773
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005774 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005775 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005776 wl->s = strdup(args[1]);
5777 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005778 }
5779 else if (!strcmp(args[0], "errorloc") ||
5780 !strcmp(args[0], "errorloc302") ||
5781 !strcmp(args[0], "errorloc303")) { /* error location */
5782 int errnum, errlen;
5783 char *err;
5784
Willy Tarreau977b8e42006-12-29 14:19:17 +01005785 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005787
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005789 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
5793
5794 errnum = atol(args[1]);
5795 if (!strcmp(args[0], "errorloc303")) {
5796 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5797 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5798 } else {
5799 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5800 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5801 }
5802
Willy Tarreau0f772532006-12-23 20:51:41 +01005803 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5804 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005805 chunk_destroy(&curproxy->errmsg[rc]);
5806 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005807 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005810
5811 if (rc >= HTTP_ERR_SIZE) {
5812 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5813 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 free(err);
5815 }
5816 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005817 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5818 int errnum, errlen, fd;
5819 char *err;
5820 struct stat stat;
5821
5822 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005823 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005824
5825 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005826 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005827 err_code |= ERR_ALERT | ERR_FATAL;
5828 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005829 }
5830
5831 fd = open(args[2], O_RDONLY);
5832 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5833 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5834 file, linenum, args[2], args[1]);
5835 if (fd >= 0)
5836 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005837 err_code |= ERR_ALERT | ERR_FATAL;
5838 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005839 }
5840
Willy Tarreau27a674e2009-08-17 07:23:33 +02005841 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005842 errlen = stat.st_size;
5843 } else {
5844 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005845 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005847 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005848 }
5849
5850 err = malloc(errlen); /* malloc() must succeed during parsing */
5851 errnum = read(fd, err, errlen);
5852 if (errnum != errlen) {
5853 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5854 file, linenum, args[2], args[1]);
5855 close(fd);
5856 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005859 }
5860 close(fd);
5861
5862 errnum = atol(args[1]);
5863 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5864 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005865 chunk_destroy(&curproxy->errmsg[rc]);
5866 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005867 break;
5868 }
5869 }
5870
5871 if (rc >= HTTP_ERR_SIZE) {
5872 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5873 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005874 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005875 free(err);
5876 }
5877 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005878 else if (!strcmp(args[0], "compression")) {
5879 struct comp *comp;
5880 if (curproxy->comp == NULL) {
5881 comp = calloc(1, sizeof(struct comp));
5882 curproxy->comp = comp;
5883 } else {
5884 comp = curproxy->comp;
5885 }
5886
5887 if (!strcmp(args[1], "algo")) {
5888 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005889 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005890
William Lallemand82fe75c2012-10-23 10:25:10 +02005891 cur_arg = 2;
5892 if (!*args[cur_arg]) {
5893 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5894 file, linenum, args[0]);
5895 err_code |= ERR_ALERT | ERR_FATAL;
5896 goto out;
5897 }
5898 while (*(args[cur_arg])) {
5899 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5900 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5901 file, linenum, args[0], args[cur_arg]);
5902 err_code |= ERR_ALERT | ERR_FATAL;
5903 goto out;
5904 }
William Lallemand552df672012-11-07 13:21:47 +01005905 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5906 curproxy->comp->algos->end(&ctx);
5907 } else {
5908 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5909 file, linenum, args[0], args[cur_arg]);
5910 err_code |= ERR_ALERT | ERR_FATAL;
5911 goto out;
5912 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005913 cur_arg ++;
5914 continue;
5915 }
5916 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005917 else if (!strcmp(args[1], "offload")) {
5918 comp->offload = 1;
5919 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005920 else if (!strcmp(args[1], "type")) {
5921 int cur_arg;
5922 cur_arg = 2;
5923 if (!*args[cur_arg]) {
5924 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5925 file, linenum, args[0]);
5926 err_code |= ERR_ALERT | ERR_FATAL;
5927 goto out;
5928 }
5929 while (*(args[cur_arg])) {
5930 comp_append_type(comp, args[cur_arg]);
5931 cur_arg ++;
5932 continue;
5933 }
5934 }
5935 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005936 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005937 file, linenum, args[0]);
5938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
5940 }
5941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005943 struct cfg_kw_list *kwl;
5944 int index;
5945
5946 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5947 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5948 if (kwl->kw[index].section != CFG_LISTEN)
5949 continue;
5950 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5951 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005952 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005953 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005954 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005955 err_code |= ERR_ALERT | ERR_FATAL;
5956 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005957 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005958 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005959 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005960 err_code |= ERR_WARN;
5961 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005962 }
Willy Tarreau93893792009-07-23 13:19:11 +02005963 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005964 }
5965 }
5966 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005967
Willy Tarreau6daf3432008-01-22 16:44:08 +01005968 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 }
Willy Tarreau93893792009-07-23 13:19:11 +02005972 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005973 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005974 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005975}
5976
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005977int
5978cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5979{
5980
5981 int err_code = 0;
5982 const char *err;
5983
5984 if (!strcmp(args[0], "userlist")) { /* new userlist */
5985 struct userlist *newul;
5986
5987 if (!*args[1]) {
5988 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5989 file, linenum, args[0]);
5990 err_code |= ERR_ALERT | ERR_FATAL;
5991 goto out;
5992 }
5993
5994 err = invalid_char(args[1]);
5995 if (err) {
5996 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5997 file, linenum, *err, args[0], args[1]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001
6002 for (newul = userlist; newul; newul = newul->next)
6003 if (!strcmp(newul->name, args[1])) {
6004 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6005 file, linenum, args[1]);
6006 err_code |= ERR_WARN;
6007 goto out;
6008 }
6009
6010 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6011 if (!newul) {
6012 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6013 err_code |= ERR_ALERT | ERR_ABORT;
6014 goto out;
6015 }
6016
6017 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6018 newul->name = strdup(args[1]);
6019
6020 if (!newul->groupusers | !newul->name) {
6021 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6022 err_code |= ERR_ALERT | ERR_ABORT;
6023 goto out;
6024 }
6025
6026 newul->next = userlist;
6027 userlist = newul;
6028
6029 } else if (!strcmp(args[0], "group")) { /* new group */
6030 int cur_arg, i;
6031 const char *err;
6032
6033 if (!*args[1]) {
6034 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6035 file, linenum, args[0]);
6036 err_code |= ERR_ALERT | ERR_FATAL;
6037 goto out;
6038 }
6039
6040 err = invalid_char(args[1]);
6041 if (err) {
6042 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6043 file, linenum, *err, args[0], args[1]);
6044 err_code |= ERR_ALERT | ERR_FATAL;
6045 goto out;
6046 }
6047
6048 for(i = 0; i < userlist->grpcnt; i++)
6049 if (!strcmp(userlist->groups[i], args[1])) {
6050 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6051 file, linenum, args[1], userlist->name);
6052 err_code |= ERR_ALERT;
6053 goto out;
6054 }
6055
6056 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6057 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6058 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6059 err_code |= ERR_ALERT | ERR_FATAL;
6060 goto out;
6061 }
6062
6063 cur_arg = 2;
6064
6065 while (*args[cur_arg]) {
6066 if (!strcmp(args[cur_arg], "users")) {
6067 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6068 cur_arg += 2;
6069 continue;
6070 } else {
6071 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6072 file, linenum, args[0]);
6073 err_code |= ERR_ALERT | ERR_FATAL;
6074 goto out;
6075 }
6076 }
6077
6078 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6079 } else if (!strcmp(args[0], "user")) { /* new user */
6080 struct auth_users *newuser;
6081 int cur_arg;
6082
6083 if (!*args[1]) {
6084 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6085 file, linenum, args[0]);
6086 err_code |= ERR_ALERT | ERR_FATAL;
6087 goto out;
6088 }
6089
6090 for (newuser = userlist->users; newuser; newuser = newuser->next)
6091 if (!strcmp(newuser->user, args[1])) {
6092 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6093 file, linenum, args[1], userlist->name);
6094 err_code |= ERR_ALERT;
6095 goto out;
6096 }
6097
6098 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6099 if (!newuser) {
6100 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6101 err_code |= ERR_ALERT | ERR_ABORT;
6102 goto out;
6103 }
6104
6105 newuser->user = strdup(args[1]);
6106
6107 newuser->next = userlist->users;
6108 userlist->users = newuser;
6109
6110 cur_arg = 2;
6111
6112 while (*args[cur_arg]) {
6113 if (!strcmp(args[cur_arg], "password")) {
6114#ifndef CONFIG_HAP_CRYPT
6115 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6116 file, linenum);
6117 err_code |= ERR_ALERT;
6118#endif
6119 newuser->pass = strdup(args[cur_arg + 1]);
6120 cur_arg += 2;
6121 continue;
6122 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6123 newuser->pass = strdup(args[cur_arg + 1]);
6124 newuser->flags |= AU_O_INSECURE;
6125 cur_arg += 2;
6126 continue;
6127 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006128 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006129 cur_arg += 2;
6130 continue;
6131 } else {
6132 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6133 file, linenum, args[0]);
6134 err_code |= ERR_ALERT | ERR_FATAL;
6135 goto out;
6136 }
6137 }
6138 } else {
6139 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6140 err_code |= ERR_ALERT | ERR_FATAL;
6141 }
6142
6143out:
6144 return err_code;
6145}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006146
6147/*
6148 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006149 * Returns the error code, 0 if OK, or any combination of :
6150 * - ERR_ABORT: must abort ASAP
6151 * - ERR_FATAL: we can continue parsing but not start the service
6152 * - ERR_WARN: a warning has been emitted
6153 * - ERR_ALERT: an alert has been emitted
6154 * Only the two first ones can stop processing, the two others are just
6155 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006157int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006159 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 FILE *f;
6161 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006163 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164
Willy Tarreaubaaee002006-06-26 02:48:02 +02006165 if ((f=fopen(file,"r")) == NULL)
6166 return -1;
6167
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006168 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006169 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006170 char *end;
6171 char *args[MAX_LINE_ARGS + 1];
6172 char *line = thisline;
6173
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174 linenum++;
6175
6176 end = line + strlen(line);
6177
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006178 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6179 /* Check if we reached the limit and the last char is not \n.
6180 * Watch out for the last line without the terminating '\n'!
6181 */
6182 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006183 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006184 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006185 }
6186
Willy Tarreaubaaee002006-06-26 02:48:02 +02006187 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006188 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189 line++;
6190
6191 arg = 0;
6192 args[arg] = line;
6193
6194 while (*line && arg < MAX_LINE_ARGS) {
6195 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6196 * C equivalent value. Other combinations left unchanged (eg: \1).
6197 */
6198 if (*line == '\\') {
6199 int skip = 0;
6200 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6201 *line = line[1];
6202 skip = 1;
6203 }
6204 else if (line[1] == 'r') {
6205 *line = '\r';
6206 skip = 1;
6207 }
6208 else if (line[1] == 'n') {
6209 *line = '\n';
6210 skip = 1;
6211 }
6212 else if (line[1] == 't') {
6213 *line = '\t';
6214 skip = 1;
6215 }
6216 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006217 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006218 unsigned char hex1, hex2;
6219 hex1 = toupper(line[2]) - '0';
6220 hex2 = toupper(line[3]) - '0';
6221 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6222 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6223 *line = (hex1<<4) + hex2;
6224 skip = 3;
6225 }
6226 else {
6227 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006228 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 }
6230 }
6231 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006232 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 end -= skip;
6234 }
6235 line++;
6236 }
6237 else if (*line == '#' || *line == '\n' || *line == '\r') {
6238 /* end of string, end of loop */
6239 *line = 0;
6240 break;
6241 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006242 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006243 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006244 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006245 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 line++;
6247 args[++arg] = line;
6248 }
6249 else {
6250 line++;
6251 }
6252 }
6253
6254 /* empty line */
6255 if (!**args)
6256 continue;
6257
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006258 if (*line) {
6259 /* we had to stop due to too many args.
6260 * Let's terminate the string, print the offending part then cut the
6261 * last arg.
6262 */
6263 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6264 line++;
6265 *line = '\0';
6266
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006267 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006268 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006269 err_code |= ERR_ALERT | ERR_FATAL;
6270 args[arg] = line;
6271 }
6272
Willy Tarreau540abe42007-05-02 20:50:16 +02006273 /* zero out remaining args and ensure that at least one entry
6274 * is zeroed out.
6275 */
6276 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 args[arg] = line;
6278 }
6279
Willy Tarreau3842f002009-06-14 11:39:52 +02006280 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006281 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006282 char *tmp;
6283
Willy Tarreau3842f002009-06-14 11:39:52 +02006284 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006285 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006286 for (arg=0; *args[arg+1]; arg++)
6287 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006288 *tmp = '\0'; // fix the next arg to \0
6289 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006290 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006291 else if (!strcmp(args[0], "default")) {
6292 kwm = KWM_DEF;
6293 for (arg=0; *args[arg+1]; arg++)
6294 args[arg] = args[arg+1]; // shift args after inversion
6295 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006296
William Lallemand0f99e342011-10-12 17:50:54 +02006297 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6298 strcmp(args[0], "log") != 0) {
6299 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006300 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006301 }
6302
Willy Tarreau977b8e42006-12-29 14:19:17 +01006303 if (!strcmp(args[0], "listen") ||
6304 !strcmp(args[0], "frontend") ||
6305 !strcmp(args[0], "backend") ||
6306 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006307 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006309 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006310 cursection = strdup(args[0]);
6311 }
6312 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006314 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006315 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006316 }
6317 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006318 confsect = CFG_USERLIST;
6319 free(cursection);
6320 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006321 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006322 else if (!strcmp(args[0], "peers")) {
6323 confsect = CFG_PEERS;
6324 free(cursection);
6325 cursection = strdup(args[0]);
6326 }
6327
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 /* else it's a section keyword */
6329
6330 switch (confsect) {
6331 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006332 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 break;
6334 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006335 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006337 case CFG_USERLIST:
6338 err_code |= cfg_parse_users(file, linenum, args, kwm);
6339 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006340 case CFG_PEERS:
6341 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6342 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006343 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006344 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006345 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006347
6348 if (err_code & ERR_ABORT)
6349 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006351 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006352 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006353 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006354 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006355}
6356
Willy Tarreaubb925012009-07-23 13:36:36 +02006357/*
6358 * Returns the error code, 0 if OK, or any combination of :
6359 * - ERR_ABORT: must abort ASAP
6360 * - ERR_FATAL: we can continue parsing but not start the service
6361 * - ERR_WARN: a warning has been emitted
6362 * - ERR_ALERT: an alert has been emitted
6363 * Only the two first ones can stop processing, the two others are just
6364 * indicators.
6365 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006366int check_config_validity()
6367{
6368 int cfgerr = 0;
6369 struct proxy *curproxy = NULL;
6370 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006371 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006372 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006373 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006374 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006376 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006377 /*
6378 * Now, check for the integrity of all that we have collected.
6379 */
6380
6381 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006382 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383
Willy Tarreau193b8c62012-11-22 00:17:38 +01006384 if (!global.tune.max_http_hdr)
6385 global.tune.max_http_hdr = MAX_HTTP_HDR;
6386
6387 if (!global.tune.cookie_len)
6388 global.tune.cookie_len = CAPTURE_LEN;
6389
6390 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6391
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006392 /* first, we will invert the proxy list order */
6393 curproxy = NULL;
6394 while (proxy) {
6395 struct proxy *next;
6396
6397 next = proxy->next;
6398 proxy->next = curproxy;
6399 curproxy = proxy;
6400 if (!next)
6401 break;
6402 proxy = next;
6403 }
6404
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006406 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006407 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006408 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006409 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006410 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006411 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006412 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006413
Willy Tarreau050536d2012-10-04 08:47:34 +02006414 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006415 /* proxy ID not set, use automatic numbering with first
6416 * spare entry starting with next_pxid.
6417 */
6418 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6419 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6420 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006421 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006422 next_pxid++;
6423
Willy Tarreau55ea7572007-06-17 19:56:27 +02006424
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006426 /* ensure we don't keep listeners uselessly bound */
6427 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 curproxy = curproxy->next;
6429 continue;
6430 }
6431
Willy Tarreau16a21472012-11-19 12:39:59 +01006432 /* number of processes this proxy is bound to */
6433 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6434
Willy Tarreauff01a212009-03-15 13:46:16 +01006435 switch (curproxy->mode) {
6436 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006437 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006438 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006439 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6440 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006441 cfgerr++;
6442 }
6443
6444 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006445 Warning("config : servers will be ignored for %s '%s'.\n",
6446 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006447 break;
6448
6449 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006450 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006451 break;
6452
6453 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006454 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006455 break;
6456 }
6457
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006458 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006459 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006460 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006461 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6462 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006463 cfgerr++;
6464 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006465#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006466 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006467 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6468 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006469 cfgerr++;
6470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006471#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006472 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006473 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6474 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006475 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006476 }
6477 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006478 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006479 /* If no LB algo is set in a backend, and we're not in
6480 * transparent mode, dispatch mode nor proxy mode, we
6481 * want to use balance roundrobin by default.
6482 */
6483 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6484 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485 }
6486 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006487
Willy Tarreau1620ec32011-08-06 17:05:02 +02006488 if (curproxy->options & PR_O_DISPATCH)
6489 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6490 else if (curproxy->options & PR_O_HTTP_PROXY)
6491 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6492 else if (curproxy->options & PR_O_TRANSP)
6493 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006494
Willy Tarreau1620ec32011-08-06 17:05:02 +02006495 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6496 if (curproxy->options & PR_O_DISABLE404) {
6497 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6498 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6499 err_code |= ERR_WARN;
6500 curproxy->options &= ~PR_O_DISABLE404;
6501 }
6502 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6503 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6504 "send-state", proxy_type_str(curproxy), curproxy->id);
6505 err_code |= ERR_WARN;
6506 curproxy->options &= ~PR_O2_CHK_SNDST;
6507 }
Willy Tarreauef781042010-01-27 11:53:01 +01006508 }
6509
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006510 /* if a default backend was specified, let's find it */
6511 if (curproxy->defbe.name) {
6512 struct proxy *target;
6513
Alex Williams96532db2009-11-01 21:27:13 -05006514 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006515 if (!target) {
6516 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6517 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006518 cfgerr++;
6519 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006520 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6521 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006522 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006523 } else {
6524 free(curproxy->defbe.name);
6525 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006526 /* we force the backend to be present on at least all of
6527 * the frontend's processes.
6528 */
6529 target->bind_proc = curproxy->bind_proc ?
6530 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006531
6532 /* Emit a warning if this proxy also has some servers */
6533 if (curproxy->srv) {
6534 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6535 curproxy->id);
6536 err_code |= ERR_WARN;
6537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 }
6539 }
6540
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006541 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006542 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6543 /* map jump target for ACT_SETBE in req_rep chain */
6544 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006545 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006546 struct proxy *target;
6547
Willy Tarreaua496b602006-12-17 23:15:24 +01006548 if (exp->action != ACT_SETBE)
6549 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006550
Alex Williams96532db2009-11-01 21:27:13 -05006551 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006552 if (!target) {
6553 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6554 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006555 cfgerr++;
6556 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006557 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6558 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006559 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006560 } else {
6561 free((void *)exp->replace);
6562 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006563 /* we force the backend to be present on at least all of
6564 * the frontend's processes.
6565 */
6566 target->bind_proc = curproxy->bind_proc ?
6567 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006568 }
6569 }
6570 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006571
6572 /* find the target proxy for 'use_backend' rules */
6573 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006574 struct proxy *target;
6575
Alex Williams96532db2009-11-01 21:27:13 -05006576 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006577
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006578 if (!target) {
6579 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6580 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006581 cfgerr++;
6582 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006583 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6584 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006585 cfgerr++;
6586 } else {
6587 free((void *)rule->be.name);
6588 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006589 /* we force the backend to be present on at least all of
6590 * the frontend's processes.
6591 */
6592 target->bind_proc = curproxy->bind_proc ?
6593 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006594 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006595 }
6596
6597 /* find the target proxy for 'use_backend' rules */
6598 list_for_each_entry(srule, &curproxy->server_rules, list) {
6599 struct server *target = findserver(curproxy, srule->srv.name);
6600
6601 if (!target) {
6602 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6603 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6604 cfgerr++;
6605 continue;
6606 }
6607 free((void *)srule->srv.name);
6608 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006609 }
6610
Emeric Brunb982a3d2010-01-04 15:45:53 +01006611 /* find the target table for 'stick' rules */
6612 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6613 struct proxy *target;
6614
Emeric Brun1d33b292010-01-04 15:47:17 +01006615 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6616 if (mrule->flags & STK_IS_STORE)
6617 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6618
Emeric Brunb982a3d2010-01-04 15:45:53 +01006619 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006620 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006621 else
6622 target = curproxy;
6623
6624 if (!target) {
6625 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6626 curproxy->id, mrule->table.name);
6627 cfgerr++;
6628 }
6629 else if (target->table.size == 0) {
6630 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6631 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6632 cfgerr++;
6633 }
Willy Tarreau12785782012-04-27 21:37:17 +02006634 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6635 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006636 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6637 cfgerr++;
6638 }
6639 else {
6640 free((void *)mrule->table.name);
6641 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006642 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006643 }
6644 }
6645
6646 /* find the target table for 'store response' rules */
6647 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6648 struct proxy *target;
6649
Emeric Brun1d33b292010-01-04 15:47:17 +01006650 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6651
Emeric Brunb982a3d2010-01-04 15:45:53 +01006652 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006653 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006654 else
6655 target = curproxy;
6656
6657 if (!target) {
6658 Alert("Proxy '%s': unable to find store table '%s'.\n",
6659 curproxy->id, mrule->table.name);
6660 cfgerr++;
6661 }
6662 else if (target->table.size == 0) {
6663 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6664 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6665 cfgerr++;
6666 }
Willy Tarreau12785782012-04-27 21:37:17 +02006667 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6668 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006669 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6670 cfgerr++;
6671 }
6672 else {
6673 free((void *)mrule->table.name);
6674 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006675 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006676 }
6677 }
6678
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006679 /* find the target table for 'tcp-request' layer 4 rules */
6680 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6681 struct proxy *target;
6682
Willy Tarreaub4c84932013-07-23 19:15:30 +02006683 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006684 continue;
6685
6686 if (trule->act_prm.trk_ctr.table.n)
6687 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6688 else
6689 target = curproxy;
6690
6691 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006692 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6693 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006694 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006695 cfgerr++;
6696 }
6697 else if (target->table.size == 0) {
6698 Alert("Proxy '%s': table '%s' used but not configured.\n",
6699 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6700 cfgerr++;
6701 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006702 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6703 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6704 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 +01006705 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006706 cfgerr++;
6707 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006708 else {
6709 free(trule->act_prm.trk_ctr.table.n);
6710 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006711 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006712 * to pass a list of counters to track and allocate them right here using
6713 * stktable_alloc_data_type().
6714 */
6715 }
6716 }
6717
Willy Tarreaud1f96522010-08-03 19:34:32 +02006718 /* find the target table for 'tcp-request' layer 6 rules */
6719 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6720 struct proxy *target;
6721
Willy Tarreaub4c84932013-07-23 19:15:30 +02006722 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006723 continue;
6724
6725 if (trule->act_prm.trk_ctr.table.n)
6726 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6727 else
6728 target = curproxy;
6729
6730 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006731 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6732 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006733 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006734 cfgerr++;
6735 }
6736 else if (target->table.size == 0) {
6737 Alert("Proxy '%s': table '%s' used but not configured.\n",
6738 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6739 cfgerr++;
6740 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006741 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6742 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6743 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 +01006744 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006745 cfgerr++;
6746 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006747 else {
6748 free(trule->act_prm.trk_ctr.table.n);
6749 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006750 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006751 * to pass a list of counters to track and allocate them right here using
6752 * stktable_alloc_data_type().
6753 */
6754 }
6755 }
6756
Emeric Brun32da3c42010-09-23 18:39:19 +02006757 if (curproxy->table.peers.name) {
6758 struct peers *curpeers = peers;
6759
6760 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6761 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6762 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006763 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006764 break;
6765 }
6766 }
6767
6768 if (!curpeers) {
6769 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6770 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006771 free((void *)curproxy->table.peers.name);
6772 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006773 cfgerr++;
6774 }
6775 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006776 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6777 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006778 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006779 cfgerr++;
6780 }
6781 }
6782
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006783 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006784 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006785 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6786 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6787 "proxy", curproxy->id);
6788 cfgerr++;
6789 goto out_uri_auth_compat;
6790 }
6791
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006792 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006793 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006794 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006795 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006796
Willy Tarreau95fa4692010-02-01 13:05:50 +01006797 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6798 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006799
6800 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006801 uri_auth_compat_req[i++] = "realm";
6802 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6803 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006804
Willy Tarreau95fa4692010-02-01 13:05:50 +01006805 uri_auth_compat_req[i++] = "unless";
6806 uri_auth_compat_req[i++] = "{";
6807 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6808 uri_auth_compat_req[i++] = "}";
6809 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006810
Willy Tarreauff011f22011-01-06 17:51:27 +01006811 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6812 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006813 cfgerr++;
6814 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006815 }
6816
Willy Tarreauff011f22011-01-06 17:51:27 +01006817 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006818
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006819 if (curproxy->uri_auth->auth_realm) {
6820 free(curproxy->uri_auth->auth_realm);
6821 curproxy->uri_auth->auth_realm = NULL;
6822 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006823
6824 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006825 }
6826out_uri_auth_compat:
6827
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006828 /* compile the log format */
6829 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006830 if (curproxy->conf.logformat_string != default_http_log_format &&
6831 curproxy->conf.logformat_string != default_tcp_log_format &&
6832 curproxy->conf.logformat_string != clf_http_log_format)
6833 free(curproxy->conf.logformat_string);
6834 curproxy->conf.logformat_string = NULL;
6835 free(curproxy->conf.lfs_file);
6836 curproxy->conf.lfs_file = NULL;
6837 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006838 }
6839
Willy Tarreau62a61232013-04-12 18:13:46 +02006840 if (curproxy->conf.logformat_string) {
6841 curproxy->conf.args.ctx = ARGC_LOG;
6842 curproxy->conf.args.file = curproxy->conf.lfs_file;
6843 curproxy->conf.args.line = curproxy->conf.lfs_line;
6844 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006845 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006846 curproxy->conf.args.file = NULL;
6847 curproxy->conf.args.line = 0;
6848 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006849
Willy Tarreau62a61232013-04-12 18:13:46 +02006850 if (curproxy->conf.uniqueid_format_string) {
6851 curproxy->conf.args.ctx = ARGC_UIF;
6852 curproxy->conf.args.file = curproxy->conf.uif_file;
6853 curproxy->conf.args.line = curproxy->conf.uif_line;
6854 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006855 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006856 curproxy->conf.args.file = NULL;
6857 curproxy->conf.args.line = 0;
6858 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006859
6860 /* only now we can check if some args remain unresolved */
6861 cfgerr += smp_resolve_args(curproxy);
6862 if (!cfgerr)
6863 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006864
Willy Tarreau2738a142006-07-08 17:28:09 +02006865 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006866 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006867 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006868 (!curproxy->timeout.connect ||
6869 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006870 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006871 " | While not properly invalid, you will certainly encounter various problems\n"
6872 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006873 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006874 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006875 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006876 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006877
Willy Tarreau1fa31262007-12-03 00:36:16 +01006878 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6879 * We must still support older configurations, so let's find out whether those
6880 * parameters have been set or must be copied from contimeouts.
6881 */
6882 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006883 if (!curproxy->timeout.tarpit ||
6884 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006885 /* tarpit timeout not set. We search in the following order:
6886 * default.tarpit, curr.connect, default.connect.
6887 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006888 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006889 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006890 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006891 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006892 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006893 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006894 }
6895 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006896 (!curproxy->timeout.queue ||
6897 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006898 /* queue timeout not set. We search in the following order:
6899 * default.queue, curr.connect, default.connect.
6900 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006901 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006902 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006903 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006904 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006905 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006906 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006907 }
6908 }
6909
Willy Tarreau1620ec32011-08-06 17:05:02 +02006910 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006911 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6912 curproxy->check_req = (char *)malloc(curproxy->check_len);
6913 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006914 }
6915
Willy Tarreau193b8c62012-11-22 00:17:38 +01006916 /* ensure that cookie capture length is not too large */
6917 if (curproxy->capture_len >= global.tune.cookie_len) {
6918 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6919 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6920 err_code |= ERR_WARN;
6921 curproxy->capture_len = global.tune.cookie_len - 1;
6922 }
6923
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006924 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006925 if (curproxy->nb_req_cap) {
6926 if (curproxy->mode == PR_MODE_HTTP) {
6927 curproxy->req_cap_pool = create_pool("ptrcap",
6928 curproxy->nb_req_cap * sizeof(char *),
6929 MEM_F_SHARED);
6930 } else {
6931 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6932 proxy_type_str(curproxy), curproxy->id);
6933 err_code |= ERR_WARN;
6934 curproxy->to_log &= ~LW_REQHDR;
6935 curproxy->nb_req_cap = 0;
6936 }
6937 }
6938
6939 if (curproxy->nb_rsp_cap) {
6940 if (curproxy->mode == PR_MODE_HTTP) {
6941 curproxy->rsp_cap_pool = create_pool("ptrcap",
6942 curproxy->nb_rsp_cap * sizeof(char *),
6943 MEM_F_SHARED);
6944 } else {
6945 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6946 proxy_type_str(curproxy), curproxy->id);
6947 err_code |= ERR_WARN;
6948 curproxy->to_log &= ~LW_REQHDR;
6949 curproxy->nb_rsp_cap = 0;
6950 }
6951 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006952
Willy Tarreaubaaee002006-06-26 02:48:02 +02006953 /* first, we will invert the servers list order */
6954 newsrv = NULL;
6955 while (curproxy->srv) {
6956 struct server *next;
6957
6958 next = curproxy->srv->next;
6959 curproxy->srv->next = newsrv;
6960 newsrv = curproxy->srv;
6961 if (!next)
6962 break;
6963 curproxy->srv = next;
6964 }
6965
Willy Tarreau17edc812014-01-03 12:14:34 +01006966 /* Check that no server name conflicts. This causes trouble in the stats.
6967 * We only emit a warning for the first conflict affecting each server,
6968 * in order to avoid combinatory explosion if all servers have the same
6969 * name. We do that only for servers which do not have an explicit ID,
6970 * because these IDs were made also for distinguishing them and we don't
6971 * want to annoy people who correctly manage them.
6972 */
6973 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6974 struct server *other_srv;
6975
6976 if (newsrv->puid)
6977 continue;
6978
6979 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6980 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6981 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6982 newsrv->conf.file, newsrv->conf.line,
6983 proxy_type_str(curproxy), curproxy->id,
6984 newsrv->id, other_srv->conf.line);
6985 break;
6986 }
6987 }
6988 }
6989
Willy Tarreaudd701652010-05-25 23:03:02 +02006990 /* assign automatic UIDs to servers which don't have one yet */
6991 next_id = 1;
6992 newsrv = curproxy->srv;
6993 while (newsrv != NULL) {
6994 if (!newsrv->puid) {
6995 /* server ID not set, use automatic numbering with first
6996 * spare entry starting with next_svid.
6997 */
6998 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6999 newsrv->conf.id.key = newsrv->puid = next_id;
7000 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7001 }
7002 next_id++;
7003 newsrv = newsrv->next;
7004 }
7005
Willy Tarreau20697042007-11-15 23:26:18 +01007006 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007007 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008
Willy Tarreau62c3be22012-01-20 13:12:32 +01007009 /*
7010 * If this server supports a maxconn parameter, it needs a dedicated
7011 * tasks to fill the emptied slots when a connection leaves.
7012 * Also, resolve deferred tracking dependency if needed.
7013 */
7014 newsrv = curproxy->srv;
7015 while (newsrv != NULL) {
7016 if (newsrv->minconn > newsrv->maxconn) {
7017 /* Only 'minconn' was specified, or it was higher than or equal
7018 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7019 * this will avoid further useless expensive computations.
7020 */
7021 newsrv->maxconn = newsrv->minconn;
7022 } else if (newsrv->maxconn && !newsrv->minconn) {
7023 /* minconn was not specified, so we set it to maxconn */
7024 newsrv->minconn = newsrv->maxconn;
7025 }
7026
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007027#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007028 if (newsrv->use_ssl || newsrv->check.use_ssl)
7029 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007030#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007031
Willy Tarreau2f075e92013-12-03 11:11:34 +01007032 /* set the check type on the server */
7033 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7034
Willy Tarreau62c3be22012-01-20 13:12:32 +01007035 if (newsrv->trackit) {
7036 struct proxy *px;
7037 struct server *srv;
7038 char *pname, *sname;
7039
7040 pname = newsrv->trackit;
7041 sname = strrchr(pname, '/');
7042
7043 if (sname)
7044 *sname++ = '\0';
7045 else {
7046 sname = pname;
7047 pname = NULL;
7048 }
7049
7050 if (pname) {
7051 px = findproxy(pname, PR_CAP_BE);
7052 if (!px) {
7053 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7054 proxy_type_str(curproxy), curproxy->id,
7055 newsrv->id, pname);
7056 cfgerr++;
7057 goto next_srv;
7058 }
7059 } else
7060 px = curproxy;
7061
7062 srv = findserver(px, sname);
7063 if (!srv) {
7064 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7065 proxy_type_str(curproxy), curproxy->id,
7066 newsrv->id, sname);
7067 cfgerr++;
7068 goto next_srv;
7069 }
7070
Willy Tarreauff5ae352013-12-11 20:36:34 +01007071 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007072 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7073 "tracking as it does not have checks enabled.\n",
7074 proxy_type_str(curproxy), curproxy->id,
7075 newsrv->id, px->id, srv->id);
7076 cfgerr++;
7077 goto next_srv;
7078 }
7079
7080 if (curproxy != px &&
7081 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7082 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7083 "tracking: disable-on-404 option inconsistency.\n",
7084 proxy_type_str(curproxy), curproxy->id,
7085 newsrv->id, px->id, srv->id);
7086 cfgerr++;
7087 goto next_srv;
7088 }
7089
7090 /* if the other server is forced disabled, we have to do the same here */
7091 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007092 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007093 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007094 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007095 }
7096
7097 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007098 newsrv->tracknext = srv->trackers;
7099 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007100
7101 free(newsrv->trackit);
7102 newsrv->trackit = NULL;
7103 }
7104 next_srv:
7105 newsrv = newsrv->next;
7106 }
7107
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007108 /* We have to initialize the server lookup mechanism depending
7109 * on what LB algorithm was choosen.
7110 */
7111
7112 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7113 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7114 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007115 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7116 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7117 init_server_map(curproxy);
7118 } else {
7119 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7120 fwrr_init_server_groups(curproxy);
7121 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007122 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007123
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007124 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007125 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7126 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7127 fwlc_init_server_tree(curproxy);
7128 } else {
7129 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7130 fas_init_server_tree(curproxy);
7131 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007132 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007133
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007134 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007135 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7136 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7137 chash_init_server_tree(curproxy);
7138 } else {
7139 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7140 init_server_map(curproxy);
7141 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007142 break;
7143 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007144
7145 if (curproxy->options & PR_O_LOGASAP)
7146 curproxy->to_log &= ~LW_BYTES;
7147
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007148 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007149 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007150 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7151 proxy_type_str(curproxy), curproxy->id);
7152 err_code |= ERR_WARN;
7153 }
7154
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007155 if (curproxy->mode != PR_MODE_HTTP) {
7156 int optnum;
7157
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007158 if (curproxy->uri_auth) {
7159 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7160 proxy_type_str(curproxy), curproxy->id);
7161 err_code |= ERR_WARN;
7162 curproxy->uri_auth = NULL;
7163 }
7164
Willy Tarreau87cf5142011-08-19 22:57:24 +02007165 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007166 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7167 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7168 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007169 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007170 }
7171
7172 if (curproxy->options & PR_O_ORGTO) {
7173 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7174 "originalto", proxy_type_str(curproxy), curproxy->id);
7175 err_code |= ERR_WARN;
7176 curproxy->options &= ~PR_O_ORGTO;
7177 }
7178
7179 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7180 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7181 (curproxy->cap & cfg_opts[optnum].cap) &&
7182 (curproxy->options & cfg_opts[optnum].val)) {
7183 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7184 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7185 err_code |= ERR_WARN;
7186 curproxy->options &= ~cfg_opts[optnum].val;
7187 }
7188 }
7189
7190 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7191 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7192 (curproxy->cap & cfg_opts2[optnum].cap) &&
7193 (curproxy->options2 & cfg_opts2[optnum].val)) {
7194 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7195 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7196 err_code |= ERR_WARN;
7197 curproxy->options2 &= ~cfg_opts2[optnum].val;
7198 }
7199 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007200
Pieter Baauwd551fb52013-05-08 22:49:23 +02007201#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007202 if (curproxy->conn_src.bind_hdr_occ) {
7203 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007204 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007205 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007206 err_code |= ERR_WARN;
7207 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007208#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007209 }
7210
Willy Tarreaubaaee002006-06-26 02:48:02 +02007211 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007212 * ensure that we're not cross-dressing a TCP server into HTTP.
7213 */
7214 newsrv = curproxy->srv;
7215 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007216 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007217 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7218 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007219 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007220 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007221
Willy Tarreau0cec3312011-10-31 13:49:26 +01007222 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7223 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7224 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7225 err_code |= ERR_WARN;
7226 }
7227
Willy Tarreau82ffa392013-08-13 17:19:08 +02007228 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7229 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7230 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7231 err_code |= ERR_WARN;
7232 }
7233
Pieter Baauwd551fb52013-05-08 22:49:23 +02007234#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007235 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7236 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007237 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 +01007238 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007239 err_code |= ERR_WARN;
7240 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007241#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007242 newsrv = newsrv->next;
7243 }
7244
Willy Tarreauc1a21672009-08-16 22:37:44 +02007245 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007246 if (!curproxy->accept)
7247 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007248
Willy Tarreauc1a21672009-08-16 22:37:44 +02007249 if (curproxy->tcp_req.inspect_delay ||
7250 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007251 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007252
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007253 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007254 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007255 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007256 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007257
7258 /* both TCP and HTTP must check switching rules */
7259 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7260 }
7261
7262 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007263 if (curproxy->tcp_req.inspect_delay ||
7264 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7265 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7266
Emeric Brun97679e72010-09-23 17:56:44 +02007267 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7268 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7269
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007270 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007271 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007272 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007273 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007274
7275 /* If the backend does requires RDP cookie persistence, we have to
7276 * enable the corresponding analyser.
7277 */
7278 if (curproxy->options2 & PR_O2_RDPC_PRST)
7279 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7280 }
7281
Emeric Brunc52962f2012-11-15 18:28:02 +01007282#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007283 /* Configure SSL for each bind line.
7284 * Note: if configuration fails at some point, the ->ctx member
7285 * remains NULL so that listeners can later detach.
7286 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007287 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007288 if (!bind_conf->is_ssl) {
7289 if (bind_conf->default_ctx) {
7290 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7291 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7292 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007293 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007294 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007295 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007296 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007297 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007298 cfgerr++;
7299 continue;
7300 }
7301
Emeric Brun4b3091e2012-09-24 15:48:52 +02007302 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007303 Alert("Unable to allocate SSL session cache.\n");
7304 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007305 continue;
7306 }
7307
Emeric Brunfc0421f2012-09-07 17:30:07 +02007308 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007309 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007310 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007311#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007312
Willy Tarreaue6b98942007-10-29 01:09:36 +01007313 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007314 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007315 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007316 if (!listener->luid) {
7317 /* listener ID not set, use automatic numbering with first
7318 * spare entry starting with next_luid.
7319 */
7320 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7321 listener->conf.id.key = listener->luid = next_id;
7322 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007323 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007324 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007325
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007326 /* enable separate counters */
7327 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7328 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007329 if (!listener->name)
7330 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007331 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007332
Willy Tarreaue6b98942007-10-29 01:09:36 +01007333 if (curproxy->options & PR_O_TCP_NOLING)
7334 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007335 if (!listener->maxconn)
7336 listener->maxconn = curproxy->maxconn;
7337 if (!listener->backlog)
7338 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007339 if (!listener->maxaccept)
7340 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7341
7342 /* we want to have an optimal behaviour on single process mode to
7343 * maximize the work at once, but in multi-process we want to keep
7344 * some fairness between processes, so we target half of the max
7345 * number of events to be balanced over all the processes the proxy
7346 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7347 * used to disable the limit.
7348 */
7349 if (listener->maxaccept > 0) {
7350 if (nbproc > 1)
7351 listener->maxaccept = (listener->maxaccept + 1) / 2;
7352 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7353 }
7354
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007355 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007356 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007357 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007358 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007359
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007360 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7361 listener->options |= LI_O_TCP_RULES;
7362
Willy Tarreaude3041d2010-05-31 10:56:17 +02007363 if (curproxy->mon_mask.s_addr)
7364 listener->options |= LI_O_CHK_MONNET;
7365
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007366 /* smart accept mode is automatic in HTTP mode */
7367 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007368 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007369 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7370 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007371 }
7372
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007373 /* Release unused SSL configs */
7374 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7375 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007376 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007377#ifdef USE_OPENSSL
7378 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007379 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007380 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007381 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007382 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007383#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007384 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007385
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007386 /* Check multi-process mode compatibility for the current proxy */
7387 if (global.nbproc > 1) {
7388 int nbproc = 0;
7389 if (curproxy->bind_proc) {
7390 int proc;
7391 for (proc = 0; proc < global.nbproc; proc++) {
7392 if (curproxy->bind_proc & (1 << proc)) {
7393 nbproc++;
7394 }
7395 }
7396 } else {
7397 nbproc = global.nbproc;
7398 }
7399 if (curproxy->table.peers.name) {
7400 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7401 curproxy->id);
7402 cfgerr++;
7403 }
7404 if (nbproc > 1) {
7405 if (curproxy->uri_auth) {
7406 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7407 curproxy->id);
7408 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7409 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7410 curproxy->id);
7411 }
7412 }
7413 if (curproxy->appsession_name) {
7414 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7415 curproxy->id);
7416 }
7417 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7418 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7419 curproxy->id);
7420 }
7421 }
7422 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007423
7424 /* create the task associated with the proxy */
7425 curproxy->task = task_new();
7426 if (curproxy->task) {
7427 curproxy->task->context = curproxy;
7428 curproxy->task->process = manage_proxy;
7429 /* no need to queue, it will be done automatically if some
7430 * listener gets limited.
7431 */
7432 curproxy->task->expire = TICK_ETERNITY;
7433 } else {
7434 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7435 curproxy->id);
7436 cfgerr++;
7437 }
7438
Willy Tarreaubaaee002006-06-26 02:48:02 +02007439 curproxy = curproxy->next;
7440 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007441
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007442 /* Check multi-process mode compatibility */
7443 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007444 if (global.stats_fe && !global.stats_fe->bind_proc) {
7445 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 +01007446 }
7447 }
7448
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007449 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7450 struct auth_users *curuser;
7451 int g;
7452
7453 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7454 unsigned int group_mask = 0;
7455 char *group = NULL;
7456
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007457 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007458 continue;
7459
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007460 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007461
7462 for (g = 0; g < curuserlist->grpcnt; g++)
7463 if (!strcmp(curuserlist->groups[g], group))
7464 break;
7465
7466 if (g == curuserlist->grpcnt) {
7467 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7468 curuserlist->name, group, curuser->user);
7469 err_code |= ERR_ALERT | ERR_FATAL;
7470 goto out;
7471 }
7472
7473 group_mask |= (1 << g);
7474 }
7475
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007476 free(curuser->u.groups);
7477 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007478 }
7479
7480 for (g = 0; g < curuserlist->grpcnt; g++) {
7481 char *user = NULL;
7482
7483 if (!curuserlist->groupusers[g])
7484 continue;
7485
7486 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7487 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7488 if (!strcmp(curuser->user, user))
7489 break;
7490
7491 if (!curuser) {
7492 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7493 curuserlist->name, user, curuserlist->groups[g]);
7494 err_code |= ERR_ALERT | ERR_FATAL;
7495 goto out;
7496 }
7497
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007498 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007499 }
7500
7501 free(curuserlist->groupusers[g]);
7502 }
7503
7504 free(curuserlist->groupusers);
7505
7506#ifdef DEBUG_AUTH
7507 for (g = 0; g < curuserlist->grpcnt; g++) {
7508 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7509
7510 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007511 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007512 fprintf(stderr, " %s", curuser->user);
7513 }
7514
7515 fprintf(stderr, "\n");
7516 }
7517#endif
7518
Willy Tarreaufbb78422011-06-05 15:38:35 +02007519 }
7520
7521 /* automatically compute fullconn if not set. We must not do it in the
7522 * loop above because cross-references are not yet fully resolved.
7523 */
7524 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7525 /* If <fullconn> is not set, let's set it to 10% of the sum of
7526 * the possible incoming frontend's maxconns.
7527 */
7528 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7529 struct proxy *fe;
7530 int total = 0;
7531
7532 /* sum up the number of maxconns of frontends which
7533 * reference this backend at least once or which are
7534 * the same one ('listen').
7535 */
7536 for (fe = proxy; fe; fe = fe->next) {
7537 struct switching_rule *rule;
7538 struct hdr_exp *exp;
7539 int found = 0;
7540
7541 if (!(fe->cap & PR_CAP_FE))
7542 continue;
7543
7544 if (fe == curproxy) /* we're on a "listen" instance */
7545 found = 1;
7546
7547 if (fe->defbe.be == curproxy) /* "default_backend" */
7548 found = 1;
7549
7550 /* check if a "use_backend" rule matches */
7551 if (!found) {
7552 list_for_each_entry(rule, &fe->switching_rules, list) {
7553 if (rule->be.backend == curproxy) {
7554 found = 1;
7555 break;
7556 }
7557 }
7558 }
7559
7560 /* check if a "reqsetbe" rule matches */
7561 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7562 if (exp->action == ACT_SETBE &&
7563 (struct proxy *)exp->replace == curproxy) {
7564 found = 1;
7565 break;
7566 }
7567 }
7568
7569 /* now we've checked all possible ways to reference a backend
7570 * from a frontend.
7571 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007572 if (!found)
7573 continue;
7574 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007575 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007576 /* we have the sum of the maxconns in <total>. We only
7577 * keep 10% of that sum to set the default fullconn, with
7578 * a hard minimum of 1 (to avoid a divide by zero).
7579 */
7580 curproxy->fullconn = (total + 9) / 10;
7581 if (!curproxy->fullconn)
7582 curproxy->fullconn = 1;
7583 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007584 }
7585
Willy Tarreau056f5682010-06-06 15:51:11 +02007586 /* initialize stick-tables on backend capable proxies. This must not
7587 * be done earlier because the data size may be discovered while parsing
7588 * other proxies.
7589 */
Godbach9703e662013-12-11 21:11:41 +08007590 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7591 if (!stktable_init(&curproxy->table)) {
7592 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7593 cfgerr++;
7594 }
7595 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007596
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007597 /*
7598 * Recount currently required checks.
7599 */
7600
7601 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7602 int optnum;
7603
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007604 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7605 if (curproxy->options & cfg_opts[optnum].val)
7606 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007607
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007608 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7609 if (curproxy->options2 & cfg_opts2[optnum].val)
7610 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007611 }
7612
Willy Tarreau122541c2011-09-07 21:24:49 +02007613 if (peers) {
7614 struct peers *curpeers = peers, **last;
7615 struct peer *p, *pb;
7616
7617 /* Remove all peers sections which don't have a valid listener.
7618 * This can happen when a peers section is never referenced and
7619 * does not contain a local peer.
7620 */
7621 last = &peers;
7622 while (*last) {
7623 curpeers = *last;
7624 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007625 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007626 last = &curpeers->next;
7627 continue;
7628 }
7629
7630 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7631 curpeers->id, localpeer);
7632
7633 p = curpeers->remote;
7634 while (p) {
7635 pb = p->next;
7636 free(p->id);
7637 free(p);
7638 p = pb;
7639 }
7640
7641 /* Destroy and unlink this curpeers section.
7642 * Note: curpeers is backed up into *last.
7643 */
7644 free(curpeers->id);
7645 curpeers = curpeers->next;
7646 free(*last);
7647 *last = curpeers;
7648 }
7649 }
7650
Willy Tarreau34eb6712011-10-24 18:15:04 +02007651 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007652 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007653 MEM_F_SHARED);
7654
Willy Tarreaubb925012009-07-23 13:36:36 +02007655 if (cfgerr > 0)
7656 err_code |= ERR_ALERT | ERR_FATAL;
7657 out:
7658 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007659}
7660
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007661/*
7662 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7663 * parsing sessions.
7664 */
7665void cfg_register_keywords(struct cfg_kw_list *kwl)
7666{
7667 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7668}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007669
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007670/*
7671 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7672 */
7673void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7674{
7675 LIST_DEL(&kwl->list);
7676 LIST_INIT(&kwl->list);
7677}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007678
7679/*
7680 * Local variables:
7681 * c-indent-level: 8
7682 * c-basic-offset: 8
7683 * End:
7684 */