blob: 4c52eed3bee9561ebd8a6221deda8ed73b5afbfc [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <netdb.h>
17#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020018#include <pwd.h>
19#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020020#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020025
Willy Tarreau2dd0d472006-06-29 17:53:05 +020026#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020027#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020029#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/memory.h>
31#include <common/standard.h>
32#include <common/time.h>
33#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020034
35#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020036#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020037#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010038#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020039#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040
Willy Tarreaueb0c6142007-05-07 00:53:22 +020041#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010042#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020043#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020044#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020047#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020048#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020049#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020050#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010051#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020052#include <proto/lb_fwlc.h>
53#include <proto/lb_fwrr.h>
54#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020055#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/log.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020057#include <proto/port_range.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020058#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020060#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010061#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010062#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020063#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020064#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020065#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010066#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020067#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010069#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020070
Emeric Brunfc0421f2012-09-07 17:30:07 +020071#ifdef USE_OPENSSL
72#include <types/ssl_sock.h>
73#include <proto/ssl_sock.h>
74#include <proto/shctx.h>
75#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020076
Willy Tarreauf3c69202006-07-09 16:42:34 +020077/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
78 * ssl-hello-chk option to ensure that the remote server speaks SSL.
79 *
80 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
81 */
82const char sslv3_client_hello_pkt[] = {
83 "\x16" /* ContentType : 0x16 = Hanshake */
84 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
85 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
86 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
87 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
88 "\x03\x00" /* Hello Version : 0x0300 = v3 */
89 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
90 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
91 "\x00" /* Session ID length : empty (no session ID) */
92 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
93 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
94 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
95 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
96 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
97 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
98 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
99 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
100 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
101 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
102 "\x00\x38" "\x00\x39" "\x00\x3A"
103 "\x01" /* Compression Length : 0x01 = 1 byte for types */
104 "\x00" /* Compression Type : 0x00 = NULL compression */
105};
106
Willy Tarreau3842f002009-06-14 11:39:52 +0200107/* various keyword modifiers */
108enum kw_mod {
109 KWM_STD = 0, /* normal */
110 KWM_NO, /* "no" prefixed before the keyword */
111 KWM_DEF, /* "default" prefixed before the keyword */
112};
113
Willy Tarreau13943ab2006-12-31 00:24:10 +0100114/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100115struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116 const char *name;
117 unsigned int val;
118 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100119 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100120 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100121};
122
123/* proxy->options */
124static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100125{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100126 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
127 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
128 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
129 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
130 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
131 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100132 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100133 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
135 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
136 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
137 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
138 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100139#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100140 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100141#else
142 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100143#endif
144
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146};
147
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148/* proxy->options2 */
149static const struct cfg_opt cfg_opts2[] =
150{
151#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100152 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
153 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
154 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100155#else
156 { "splice-request", 0, 0, 0, 0 },
157 { "splice-response", 0, 0, 0, 0 },
158 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100159#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
161 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
162 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
163 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
164 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
165 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
166 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
167 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
168 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400169 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200171 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200172 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173 { NULL, 0, 0, 0 }
174};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200175
Willy Tarreau6daf3432008-01-22 16:44:08 +0100176static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200177static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
178int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100179int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200181/* List head of all known configuration keywords */
182static struct cfg_kw_list cfg_keywords = {
183 .list = LIST_HEAD_INIT(cfg_keywords.list)
184};
185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186/*
187 * converts <str> to a list of listeners which are dynamically allocated.
188 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
189 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
190 * - <port> is a numerical port from 1 to 65535 ;
191 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
192 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200193 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
194 * not NULL, it must be a valid pointer to either NULL or a freeable area that
195 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200197int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198{
199 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100200 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 int port, end;
202
203 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100206 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100207 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
209 str = next;
210 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100211 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 *next++ = 0;
213 }
214
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100215 ss2 = str2sa_range(str, &port, &end, err,
216 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
217 if (!ss2)
218 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100220 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100221 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200225
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100226 if (!port || !end) {
227 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
228 goto fail;
229 }
230
Emeric Bruned760922010-10-22 17:59:25 +0200231 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200232 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200233 goto fail;
234 }
235
236 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200237 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200238 goto fail;
239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100241 else if (ss2->ss_family == AF_UNSPEC) {
242 socklen_t addr_len;
243
244 /* We want to attach to an already bound fd whose number
245 * is in the addr part of ss2 when cast to sockaddr_in.
246 * Note that by definition there is a single listener.
247 * We still have to determine the address family to
248 * register the correct protocol.
249 */
250 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
251 addr_len = sizeof(*ss2);
252 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
253 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
254 goto fail;
255 }
256
257 port = end = get_host_port(ss2);
258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100260 /* OK the address looks correct */
261 ss = *ss2;
262
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 for (; port <= end; port++) {
264 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100265 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200266 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
267 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
268 l->frontend = curproxy;
269 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270
Willy Tarreau40aa0702013-03-10 23:51:38 +0100271 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200272 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200273 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100274 l->state = LI_INIT;
275
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100276 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200277 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100278 tcpv4_add_listener(l);
279 }
Emeric Bruned760922010-10-22 17:59:25 +0200280 else if (ss.ss_family == AF_INET6) {
281 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
282 tcpv6_add_listener(l);
283 }
284 else {
Emeric Bruned760922010-10-22 17:59:25 +0200285 uxst_add_listener(l);
286 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200287
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200288 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100289 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200290 } /* end for(port) */
291 } /* end while(next) */
292 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200293 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 fail:
295 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200296 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297}
298
Willy Tarreau977b8e42006-12-29 14:19:17 +0100299/*
300 * Sends a warning if proxy <proxy> does not have at least one of the
301 * capabilities in <cap>. An optionnal <hint> may be added at the end
302 * of the warning to help the user. Returns 1 if a warning was emitted
303 * or 0 if the condition is valid.
304 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100305int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100306{
307 char *msg;
308
309 switch (cap) {
310 case PR_CAP_BE: msg = "no backend"; break;
311 case PR_CAP_FE: msg = "no frontend"; break;
312 case PR_CAP_RS: msg = "no ruleset"; break;
313 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
314 default: msg = "not enough"; break;
315 }
316
317 if (!(proxy->cap & cap)) {
318 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100319 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100320 return 1;
321 }
322 return 0;
323}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200324
Willy Tarreau61d18892009-03-31 10:49:21 +0200325/* Report a warning if a rule is placed after a 'block' rule.
326 * Return 1 if the warning has been emitted, otherwise 0.
327 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100328int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200329{
330 if (!LIST_ISEMPTY(&proxy->block_cond)) {
331 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
332 file, line, arg);
333 return 1;
334 }
335 return 0;
336}
337
338/* Report a warning if a rule is placed after a reqrewrite rule.
339 * Return 1 if the warning has been emitted, otherwise 0.
340 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100341int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200342{
343 if (proxy->req_exp) {
344 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
345 file, line, arg);
346 return 1;
347 }
348 return 0;
349}
350
351/* Report a warning if a rule is placed after a reqadd rule.
352 * Return 1 if the warning has been emitted, otherwise 0.
353 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100354int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200355{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100356 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200357 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
358 file, line, arg);
359 return 1;
360 }
361 return 0;
362}
363
364/* Report a warning if a rule is placed after a redirect rule.
365 * Return 1 if the warning has been emitted, otherwise 0.
366 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100367int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200368{
369 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
370 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
371 file, line, arg);
372 return 1;
373 }
374 return 0;
375}
376
377/* Report a warning if a rule is placed after a 'use_backend' rule.
378 * Return 1 if the warning has been emitted, otherwise 0.
379 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100380int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200381{
382 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
383 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
384 file, line, arg);
385 return 1;
386 }
387 return 0;
388}
389
390/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100391int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200392{
393 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
394 warnif_rule_after_reqadd(proxy, file, line, arg) ||
395 warnif_rule_after_redirect(proxy, file, line, arg) ||
396 warnif_rule_after_use_backend(proxy, file, line, arg);
397}
398
399/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
403 warnif_rule_after_redirect(proxy, file, line, arg) ||
404 warnif_rule_after_use_backend(proxy, file, line, arg);
405}
406
407/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100408int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200409{
410 return warnif_rule_after_redirect(proxy, file, line, arg) ||
411 warnif_rule_after_use_backend(proxy, file, line, arg);
412}
413
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100414/* Report it if a request ACL condition uses some keywords that are incompatible
415 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
416 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
417 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100418 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100419static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100420{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100421 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200422 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100423
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100424 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100425 return 0;
426
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100427 acl = acl_cond_conflicts(cond, where);
428 if (acl) {
429 if (acl->name && *acl->name)
430 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
431 file, line, acl->name, sample_ckp_names(where));
432 else
433 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200434 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100435 return ERR_WARN;
436 }
437 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100438 return 0;
439
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100440 if (acl->name && *acl->name)
441 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200442 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100443 else
444 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200445 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100446 return ERR_WARN;
447}
448
Willy Tarreaubaaee002006-06-26 02:48:02 +0200449/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200450 * parse a line in a <global> section. Returns the error code, 0 if OK, or
451 * any combination of :
452 * - ERR_ABORT: must abort ASAP
453 * - ERR_FATAL: we can continue parsing but not start the service
454 * - ERR_WARN: a warning has been emitted
455 * - ERR_ALERT: an alert has been emitted
456 * Only the two first ones can stop processing, the two others are just
457 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200458 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200459int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200460{
Willy Tarreau058e9072009-07-20 09:30:05 +0200461 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200462 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200463
464 if (!strcmp(args[0], "global")) { /* new section */
465 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200467 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200468 else if (!strcmp(args[0], "ca-base")) {
469#ifdef USE_OPENSSL
470 if (global.ca_base != NULL) {
471 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
472 err_code |= ERR_ALERT;
473 goto out;
474 }
475 if (*(args[1]) == 0) {
476 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
477 err_code |= ERR_ALERT | ERR_FATAL;
478 goto out;
479 }
480 global.ca_base = strdup(args[1]);
481#else
482 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
483 err_code |= ERR_ALERT | ERR_FATAL;
484 goto out;
485#endif
486 }
487 else if (!strcmp(args[0], "crt-base")) {
488#ifdef USE_OPENSSL
489 if (global.crt_base != NULL) {
490 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
491 err_code |= ERR_ALERT;
492 goto out;
493 }
494 if (*(args[1]) == 0) {
495 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
496 err_code |= ERR_ALERT | ERR_FATAL;
497 goto out;
498 }
499 global.crt_base = strdup(args[1]);
500#else
501 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
502 err_code |= ERR_ALERT | ERR_FATAL;
503 goto out;
504#endif
505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200506 else if (!strcmp(args[0], "daemon")) {
507 global.mode |= MODE_DAEMON;
508 }
509 else if (!strcmp(args[0], "debug")) {
510 global.mode |= MODE_DEBUG;
511 }
512 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100513 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200515 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100516 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100519 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100521 else if (!strcmp(args[0], "nosplice")) {
522 global.tune.options &= ~GTUNE_USE_SPLICE;
523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200524 else if (!strcmp(args[0], "quiet")) {
525 global.mode |= MODE_QUIET;
526 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200527 else if (!strcmp(args[0], "tune.maxpollevents")) {
528 if (global.tune.maxpollevents != 0) {
529 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200530 err_code |= ERR_ALERT;
531 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200532 }
533 if (*(args[1]) == 0) {
534 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200535 err_code |= ERR_ALERT | ERR_FATAL;
536 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200537 }
538 global.tune.maxpollevents = atol(args[1]);
539 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100540 else if (!strcmp(args[0], "tune.maxaccept")) {
541 if (global.tune.maxaccept != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 err_code |= ERR_ALERT;
544 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100550 }
551 global.tune.maxaccept = atol(args[1]);
552 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200553 else if (!strcmp(args[0], "tune.chksize")) {
554 if (*(args[1]) == 0) {
555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT | ERR_FATAL;
557 goto out;
558 }
559 global.tune.chksize = atol(args[1]);
560 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200561#ifdef USE_OPENSSL
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100562 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200563 if (*(args[1]) == 0) {
564 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567 }
568 global.tune.sslcachesize = atol(args[1]);
569 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100570 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
571 unsigned int ssllifetime;
572 const char *res;
573
574 if (*(args[1]) == 0) {
575 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
576 err_code |= ERR_ALERT | ERR_FATAL;
577 goto out;
578 }
579
580 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
581 if (res) {
582 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
583 file, linenum, *res, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587
588 global.tune.ssllifetime = ssllifetime;
589 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100590 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
591 if (*(args[1]) == 0) {
592 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT | ERR_FATAL;
594 goto out;
595 }
596 global.tune.ssl_max_record = atol(args[1]);
597 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200598#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200599 else if (!strcmp(args[0], "tune.bufsize")) {
600 if (*(args[1]) == 0) {
601 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
602 err_code |= ERR_ALERT | ERR_FATAL;
603 goto out;
604 }
605 global.tune.bufsize = atol(args[1]);
606 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
607 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100608 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100609 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200610 }
611 else if (!strcmp(args[0], "tune.maxrewrite")) {
612 if (*(args[1]) == 0) {
613 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT | ERR_FATAL;
615 goto out;
616 }
617 global.tune.maxrewrite = atol(args[1]);
618 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
619 global.tune.maxrewrite = global.tune.bufsize / 2;
620 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100621 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
622 if (global.tune.client_rcvbuf != 0) {
623 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT;
625 goto out;
626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
631 }
632 global.tune.client_rcvbuf = atol(args[1]);
633 }
634 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
635 if (global.tune.server_rcvbuf != 0) {
636 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
637 err_code |= ERR_ALERT;
638 goto out;
639 }
640 if (*(args[1]) == 0) {
641 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
642 err_code |= ERR_ALERT | ERR_FATAL;
643 goto out;
644 }
645 global.tune.server_rcvbuf = atol(args[1]);
646 }
647 else if (!strcmp(args[0], "tune.sndbuf.client")) {
648 if (global.tune.client_sndbuf != 0) {
649 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
650 err_code |= ERR_ALERT;
651 goto out;
652 }
653 if (*(args[1]) == 0) {
654 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
655 err_code |= ERR_ALERT | ERR_FATAL;
656 goto out;
657 }
658 global.tune.client_sndbuf = atol(args[1]);
659 }
660 else if (!strcmp(args[0], "tune.sndbuf.server")) {
661 if (global.tune.server_sndbuf != 0) {
662 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT;
664 goto out;
665 }
666 if (*(args[1]) == 0) {
667 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
668 err_code |= ERR_ALERT | ERR_FATAL;
669 goto out;
670 }
671 global.tune.server_sndbuf = atol(args[1]);
672 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200673 else if (!strcmp(args[0], "tune.pipesize")) {
674 if (*(args[1]) == 0) {
675 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
676 err_code |= ERR_ALERT | ERR_FATAL;
677 goto out;
678 }
679 global.tune.pipesize = atol(args[1]);
680 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100681 else if (!strcmp(args[0], "tune.http.cookielen")) {
682 if (*(args[1]) == 0) {
683 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
684 err_code |= ERR_ALERT | ERR_FATAL;
685 goto out;
686 }
687 global.tune.cookie_len = atol(args[1]) + 1;
688 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200689 else if (!strcmp(args[0], "tune.http.maxhdr")) {
690 if (*(args[1]) == 0) {
691 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
692 err_code |= ERR_ALERT | ERR_FATAL;
693 goto out;
694 }
695 global.tune.max_http_hdr = atol(args[1]);
696 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100697 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
698#ifdef USE_ZLIB
699 if (*args[1]) {
700 global.tune.zlibmemlevel = atoi(args[1]);
701 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
702 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
703 file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 } else {
708 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
709 file, linenum, args[0]);
710 err_code |= ERR_ALERT | ERR_FATAL;
711 goto out;
712 }
713#else
714 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
715 err_code |= ERR_ALERT | ERR_FATAL;
716 goto out;
717#endif
718 }
719 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
720#ifdef USE_ZLIB
721 if (*args[1]) {
722 global.tune.zlibwindowsize = atoi(args[1]);
723 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
724 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
725 file, linenum, args[0]);
726 err_code |= ERR_ALERT | ERR_FATAL;
727 goto out;
728 }
729 } else {
730 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
731 file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735#else
736 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739#endif
740 }
William Lallemandf3747832012-11-09 12:33:10 +0100741 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
742 if (*args[1]) {
743 global.tune.comp_maxlevel = atoi(args[1]);
744 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
745 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
746 file, linenum, args[0]);
747 err_code |= ERR_ALERT | ERR_FATAL;
748 goto out;
749 }
750 } else {
751 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
752 file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200757 else if (!strcmp(args[0], "uid")) {
758 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200759 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200760 err_code |= ERR_ALERT;
761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200762 }
763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200767 }
768 global.uid = atol(args[1]);
769 }
770 else if (!strcmp(args[0], "gid")) {
771 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200772 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200773 err_code |= ERR_ALERT;
774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200780 }
781 global.gid = atol(args[1]);
782 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200783 /* user/group name handling */
784 else if (!strcmp(args[0], "user")) {
785 struct passwd *ha_user;
786 if (global.uid != 0) {
787 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200788 err_code |= ERR_ALERT;
789 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200790 }
791 errno = 0;
792 ha_user = getpwnam(args[1]);
793 if (ha_user != NULL) {
794 global.uid = (int)ha_user->pw_uid;
795 }
796 else {
797 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 +0200798 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200799 }
800 }
801 else if (!strcmp(args[0], "group")) {
802 struct group *ha_group;
803 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200804 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT;
806 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200807 }
808 errno = 0;
809 ha_group = getgrnam(args[1]);
810 if (ha_group != NULL) {
811 global.gid = (int)ha_group->gr_gid;
812 }
813 else {
814 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 +0200815 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200816 }
817 }
818 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200819 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200824 }
825 global.nbproc = atol(args[1]);
826 }
827 else if (!strcmp(args[0], "maxconn")) {
828 if (global.maxconn != 0) {
829 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200830 err_code |= ERR_ALERT;
831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 }
833 if (*(args[1]) == 0) {
834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200837 }
838 global.maxconn = atol(args[1]);
839#ifdef SYSTEM_MAXCONN
840 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
841 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);
842 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200843 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200844 }
845#endif /* SYSTEM_MAXCONN */
846 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200847 else if (!strcmp(args[0], "maxsslconn")) {
848#ifdef USE_OPENSSL
849 if (*(args[1]) == 0) {
850 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 global.maxsslconn = atol(args[1]);
855#else
Emeric Brun0914df82012-10-02 18:45:42 +0200856 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200859#endif
860 }
Emeric Brun850efd52014-01-29 12:24:34 +0100861 else if (!strcmp(args[0], "ssl-server-verify")) {
862 if (*(args[1]) == 0) {
863 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867 if (strcmp(args[1],"none") == 0)
868 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
869 else if (strcmp(args[1],"required") == 0)
870 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
871 else {
872 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
873 err_code |= ERR_ALERT | ERR_FATAL;
874 goto out;
875 }
876 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200877 else if (!strcmp(args[0], "maxconnrate")) {
878 if (global.cps_lim != 0) {
879 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
880 err_code |= ERR_ALERT;
881 goto out;
882 }
883 if (*(args[1]) == 0) {
884 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
885 err_code |= ERR_ALERT | ERR_FATAL;
886 goto out;
887 }
888 global.cps_lim = atol(args[1]);
889 }
Willy Tarreau93e7c002013-10-07 18:51:07 +0200890 else if (!strcmp(args[0], "maxsessrate")) {
891 if (global.sps_lim != 0) {
892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT;
894 goto out;
895 }
896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901 global.sps_lim = atol(args[1]);
902 }
Willy Tarreaue43d5322013-10-07 20:01:52 +0200903 else if (!strcmp(args[0], "maxsslrate")) {
904 if (global.ssl_lim != 0) {
905 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
906 err_code |= ERR_ALERT;
907 goto out;
908 }
909 if (*(args[1]) == 0) {
910 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
911 err_code |= ERR_ALERT | ERR_FATAL;
912 goto out;
913 }
914 global.ssl_lim = atol(args[1]);
915 }
William Lallemandd85f9172012-11-09 17:05:39 +0100916 else if (!strcmp(args[0], "maxcomprate")) {
917 if (*(args[1]) == 0) {
918 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 global.comp_rate_lim = atoi(args[1]) * 1024;
923 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100924 else if (!strcmp(args[0], "maxpipes")) {
925 if (global.maxpipes != 0) {
926 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT;
928 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100929 }
930 if (*(args[1]) == 0) {
931 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200932 err_code |= ERR_ALERT | ERR_FATAL;
933 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100934 }
935 global.maxpipes = atol(args[1]);
936 }
William Lallemand9d5f5482012-11-07 16:12:57 +0100937 else if (!strcmp(args[0], "maxzlibmem")) {
938 if (*(args[1]) == 0) {
939 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
940 err_code |= ERR_ALERT | ERR_FATAL;
941 goto out;
942 }
William Lallemande3a7d992012-11-20 11:25:20 +0100943 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +0100944 }
William Lallemand072a2bf2012-11-20 17:01:01 +0100945 else if (!strcmp(args[0], "maxcompcpuusage")) {
946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +0100952 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +0100953 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
957}
958
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 else if (!strcmp(args[0], "ulimit-n")) {
960 if (global.rlimit_nofile != 0) {
961 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200962 err_code |= ERR_ALERT;
963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964 }
965 if (*(args[1]) == 0) {
966 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200967 err_code |= ERR_ALERT | ERR_FATAL;
968 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969 }
970 global.rlimit_nofile = atol(args[1]);
971 }
972 else if (!strcmp(args[0], "chroot")) {
973 if (global.chroot != NULL) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT;
976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 }
978 if (*(args[1]) == 0) {
979 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 }
983 global.chroot = strdup(args[1]);
984 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200985 else if (!strcmp(args[0], "description")) {
986 int i, len=0;
987 char *d;
988
989 if (!*args[1]) {
990 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
991 file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995
996 for(i=1; *args[i]; i++)
997 len += strlen(args[i])+1;
998
999 if (global.desc)
1000 free(global.desc);
1001
1002 global.desc = d = (char *)calloc(1, len);
1003
1004 d += sprintf(d, "%s", args[1]);
1005 for(i=2; *args[i]; i++)
1006 d += sprintf(d, " %s", args[i]);
1007 }
1008 else if (!strcmp(args[0], "node")) {
1009 int i;
1010 char c;
1011
1012 for (i=0; args[1][i]; i++) {
1013 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001014 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1015 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001016 break;
1017 }
1018
1019 if (!i || args[1][i]) {
1020 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1021 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026
1027 if (global.node)
1028 free(global.node);
1029
1030 global.node = strdup(args[1]);
1031 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001032 else if (!strcmp(args[0], "pidfile")) {
1033 if (global.pidfile != NULL) {
1034 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001035 err_code |= ERR_ALERT;
1036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001037 }
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001042 }
1043 global.pidfile = strdup(args[1]);
1044 }
Emeric Bruned760922010-10-22 17:59:25 +02001045 else if (!strcmp(args[0], "unix-bind")) {
1046 int cur_arg = 1;
1047 while (*(args[cur_arg])) {
1048 if (!strcmp(args[cur_arg], "prefix")) {
1049 if (global.unix_bind.prefix != NULL) {
1050 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1051 err_code |= ERR_ALERT;
1052 cur_arg += 2;
1053 continue;
1054 }
1055
1056 if (*(args[cur_arg+1]) == 0) {
1057 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060 }
1061 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1062 cur_arg += 2;
1063 continue;
1064 }
1065
1066 if (!strcmp(args[cur_arg], "mode")) {
1067
1068 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1069 cur_arg += 2;
1070 continue;
1071 }
1072
1073 if (!strcmp(args[cur_arg], "uid")) {
1074
1075 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1076 cur_arg += 2;
1077 continue;
1078 }
1079
1080 if (!strcmp(args[cur_arg], "gid")) {
1081
1082 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1083 cur_arg += 2;
1084 continue;
1085 }
1086
1087 if (!strcmp(args[cur_arg], "user")) {
1088 struct passwd *user;
1089
1090 user = getpwnam(args[cur_arg + 1]);
1091 if (!user) {
1092 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1093 file, linenum, args[0], args[cur_arg + 1 ]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097
1098 global.unix_bind.ux.uid = user->pw_uid;
1099 cur_arg += 2;
1100 continue;
1101 }
1102
1103 if (!strcmp(args[cur_arg], "group")) {
1104 struct group *group;
1105
1106 group = getgrnam(args[cur_arg + 1]);
1107 if (!group) {
1108 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1109 file, linenum, args[0], args[cur_arg + 1 ]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113
1114 global.unix_bind.ux.gid = group->gr_gid;
1115 cur_arg += 2;
1116 continue;
1117 }
1118
Willy Tarreaub48f9582011-09-05 01:17:06 +02001119 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001120 file, linenum, args[0]);
1121 err_code |= ERR_ALERT | ERR_FATAL;
1122 goto out;
1123 }
1124 }
William Lallemand0f99e342011-10-12 17:50:54 +02001125 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1126 /* delete previous herited or defined syslog servers */
1127 struct logsrv *back;
1128 struct logsrv *tmp;
1129
1130 if (*(args[1]) != 0) {
1131 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
1134 }
1135
1136 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1137 LIST_DEL(&tmp->list);
1138 free(tmp);
1139 }
1140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001141 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001142 struct sockaddr_storage *sk;
1143 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001144 struct logsrv *logsrv;
1145
Willy Tarreaubaaee002006-06-26 02:48:02 +02001146 if (*(args[1]) == 0 || *(args[2]) == 0) {
1147 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001148 err_code |= ERR_ALERT | ERR_FATAL;
1149 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 }
William Lallemand0f99e342011-10-12 17:50:54 +02001151
1152 logsrv = calloc(1, sizeof(struct logsrv));
1153
1154 logsrv->facility = get_log_facility(args[2]);
1155 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001158 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 }
1160
William Lallemand0f99e342011-10-12 17:50:54 +02001161 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001162 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001163 logsrv->level = get_log_level(args[3]);
1164 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02001165 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001167 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 }
1170
William Lallemand0f99e342011-10-12 17:50:54 +02001171 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001172 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02001173 logsrv->minlvl = get_log_level(args[4]);
1174 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001175 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001177 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001178 }
1179 }
1180
Willy Tarreau902636f2013-03-10 19:44:48 +01001181 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001182 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001183 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001184 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001185 free(logsrv);
1186 goto out;
1187 }
1188 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001189
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001190 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001191 if (port1 != port2) {
1192 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1193 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001194 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001195 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001196 goto out;
1197 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001198
William Lallemand0f99e342011-10-12 17:50:54 +02001199 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001200 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001201 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203
William Lallemand0f99e342011-10-12 17:50:54 +02001204 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001205 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001206 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1207 char *name;
1208 int len;
1209
1210 if (global.log_send_hostname != NULL) {
1211 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1212 err_code |= ERR_ALERT;
1213 goto out;
1214 }
1215
1216 if (*(args[1]))
1217 name = args[1];
1218 else
1219 name = hostname;
1220
1221 len = strlen(name);
1222
1223 /* We'll add a space after the name to respect the log format */
1224 free(global.log_send_hostname);
1225 global.log_send_hostname = malloc(len + 2);
1226 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1227 }
Kevinm48936af2010-12-22 16:08:21 +00001228 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
1233 }
1234 free(global.log_tag);
1235 global.log_tag = strdup(args[1]);
1236 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001237 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1238 if (global.spread_checks != 0) {
1239 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001240 err_code |= ERR_ALERT;
1241 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001242 }
1243 if (*(args[1]) == 0) {
1244 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001245 err_code |= ERR_ALERT | ERR_FATAL;
1246 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001247 }
1248 global.spread_checks = atol(args[1]);
1249 if (global.spread_checks < 0 || global.spread_checks > 50) {
1250 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001251 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001252 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001253 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001254 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1255#ifdef USE_CPU_AFFINITY
1256 int cur_arg, i;
1257 unsigned int proc = 0;
1258 unsigned long cpus = 0;
1259
1260 if (strcmp(args[1], "all") == 0)
1261 proc = 0xFFFFFFFF;
1262 else if (strcmp(args[1], "odd") == 0)
1263 proc = 0x55555555;
1264 else if (strcmp(args[1], "even") == 0)
1265 proc = 0xAAAAAAAA;
1266 else {
1267 proc = atoi(args[1]);
1268 if (proc >= 1 && proc <= 32)
1269 proc = 1 << (proc - 1);
1270 }
1271
1272 if (!proc || !*args[2]) {
1273 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",
1274 file, linenum, args[0]);
1275 err_code |= ERR_ALERT | ERR_FATAL;
1276 goto out;
1277 }
1278
1279 cur_arg = 2;
1280 while (*args[cur_arg]) {
1281 unsigned int low, high;
1282
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001283 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001284 char *dash = strchr(args[cur_arg], '-');
1285
1286 low = high = str2uic(args[cur_arg]);
1287 if (dash)
1288 high = str2uic(dash + 1);
1289
1290 if (high < low) {
1291 unsigned int swap = low;
1292 low = high;
1293 high = swap;
1294 }
1295
1296 if (low < 0 || high >= sizeof(long) * 8) {
1297 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
1298 file, linenum, args[0], (int)(sizeof(long) * 8 - 1));
1299 err_code |= ERR_ALERT | ERR_FATAL;
1300 goto out;
1301 }
1302
1303 while (low <= high)
1304 cpus |= 1UL << low++;
1305 }
1306 else {
1307 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1308 file, linenum, args[0], args[cur_arg]);
1309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
1311 }
1312 cur_arg++;
1313 }
1314 for (i = 0; i < 32; i++)
1315 if (proc & (1 << i))
1316 global.cpu_map[i] = cpus;
1317#else
1318 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1319 err_code |= ERR_ALERT | ERR_FATAL;
1320 goto out;
1321#endif
1322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001324 struct cfg_kw_list *kwl;
1325 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001326 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001327
1328 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1329 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1330 if (kwl->kw[index].section != CFG_GLOBAL)
1331 continue;
1332 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001333 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001334 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001335 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001336 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001337 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001338 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001339 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001340 err_code |= ERR_WARN;
1341 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001342 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001343 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001344 }
1345 }
1346 }
1347
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001349 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001351
Willy Tarreau058e9072009-07-20 09:30:05 +02001352 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001353 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001354 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001355}
1356
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001357void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001359 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 defproxy.mode = PR_MODE_TCP;
1361 defproxy.state = PR_STNEW;
1362 defproxy.maxconn = cfg_maxpconn;
1363 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001364
Simon Horman66183002013-02-23 10:16:43 +09001365 defproxy.defsrv.check.inter = DEF_CHKINTR;
1366 defproxy.defsrv.check.fastinter = 0;
1367 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001368 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1369 defproxy.defsrv.agent.fastinter = 0;
1370 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001371 defproxy.defsrv.check.rise = DEF_RISETIME;
1372 defproxy.defsrv.check.fall = DEF_FALLTIME;
1373 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1374 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001375 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001376 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001377 defproxy.defsrv.maxqueue = 0;
1378 defproxy.defsrv.minconn = 0;
1379 defproxy.defsrv.maxconn = 0;
1380 defproxy.defsrv.slowstart = 0;
1381 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1382 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1383 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001384}
1385
Willy Tarreauade5ec42010-01-28 19:33:49 +01001386
1387static int create_cond_regex_rule(const char *file, int line,
1388 struct proxy *px, int dir, int action, int flags,
1389 const char *cmd, const char *reg, const char *repl,
1390 const char **cond_start)
1391{
1392 regex_t *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001393 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001394 const char *err;
1395 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001396 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001397
1398 if (px == &defproxy) {
1399 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1400 err_code |= ERR_ALERT | ERR_FATAL;
1401 goto err;
1402 }
1403
1404 if (*reg == 0) {
1405 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1406 err_code |= ERR_ALERT | ERR_FATAL;
1407 goto err;
1408 }
1409
1410 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1411 err_code |= ERR_WARN;
1412
Willy Tarreau5321c422010-01-28 20:35:13 +01001413 if (cond_start &&
1414 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001415 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1416 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1417 file, line, cmd, errmsg);
Willy Tarreau5321c422010-01-28 20:35:13 +01001418 err_code |= ERR_ALERT | ERR_FATAL;
1419 goto err;
1420 }
1421 }
1422 else if (cond_start && **cond_start) {
1423 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1424 file, line, cmd, *cond_start);
1425 err_code |= ERR_ALERT | ERR_FATAL;
1426 goto err;
1427 }
1428
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001429 err_code |= warnif_cond_conflicts(cond,
1430 (dir == SMP_OPT_DIR_REQ) ?
1431 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1432 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1433 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001434
Willy Tarreauade5ec42010-01-28 19:33:49 +01001435 preg = calloc(1, sizeof(regex_t));
1436 if (!preg) {
1437 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1438 err_code = ERR_ALERT | ERR_FATAL;
1439 goto err;
1440 }
1441
1442 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1443 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1444 err_code = ERR_ALERT | ERR_FATAL;
1445 goto err;
1446 }
1447
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001448 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001449 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001450 if (repl && err) {
1451 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1452 file, line, cmd, *err);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 goto err;
1455 }
1456
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001457 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001458 err_code |= ERR_WARN;
1459
Willy Tarreauf4068b62012-05-08 17:37:49 +02001460 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001461 return err_code;
1462 err:
Willy Tarreauf4068b62012-05-08 17:37:49 +02001463 free(errmsg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001464 free(preg);
1465 return err_code;
1466}
1467
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001469 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001470 * Returns the error code, 0 if OK, or any combination of :
1471 * - ERR_ABORT: must abort ASAP
1472 * - ERR_FATAL: we can continue parsing but not start the service
1473 * - ERR_WARN: a warning has been emitted
1474 * - ERR_ALERT: an alert has been emitted
1475 * Only the two first ones can stop processing, the two others are just
1476 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001478int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1479{
1480 static struct peers *curpeers = NULL;
1481 struct peer *newpeer = NULL;
1482 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001483 struct bind_conf *bind_conf;
1484 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001485 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001486 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001487
1488 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001489 if (!*args[1]) {
1490 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
1491 err_code |= ERR_ALERT | ERR_FATAL;
1492 goto out;
1493 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001494
1495 err = invalid_char(args[1]);
1496 if (err) {
1497 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1498 file, linenum, *err, args[0], args[1]);
1499 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001500 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001501 }
1502
1503 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1504 /*
1505 * If there are two proxies with the same name only following
1506 * combinations are allowed:
1507 */
1508 if (strcmp(curpeers->id, args[1]) == 0) {
1509 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1510 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1511 err_code |= ERR_WARN;
1512 }
1513 }
1514
1515 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1516 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1517 err_code |= ERR_ALERT | ERR_ABORT;
1518 goto out;
1519 }
1520
1521 curpeers->next = peers;
1522 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001523 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001524 curpeers->conf.line = linenum;
1525 curpeers->last_change = now.tv_sec;
1526 curpeers->id = strdup(args[1]);
1527 }
1528 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001529 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001530 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001531 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001532
1533 if (!*args[2]) {
1534 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1535 file, linenum, args[0]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539
1540 err = invalid_char(args[1]);
1541 if (err) {
1542 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1543 file, linenum, *err, args[1]);
1544 err_code |= ERR_ALERT | ERR_FATAL;
1545 goto out;
1546 }
1547
1548 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1549 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1550 err_code |= ERR_ALERT | ERR_ABORT;
1551 goto out;
1552 }
1553
1554 /* the peers are linked backwards first */
1555 curpeers->count++;
1556 newpeer->next = curpeers->remote;
1557 curpeers->remote = newpeer;
1558 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001559 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001560 newpeer->conf.line = linenum;
1561
1562 newpeer->last_change = now.tv_sec;
1563 newpeer->id = strdup(args[1]);
1564
Willy Tarreau902636f2013-03-10 19:44:48 +01001565 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001566 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001567 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001568 err_code |= ERR_ALERT | ERR_FATAL;
1569 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001570 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001571
1572 proto = protocol_by_family(sk->ss_family);
1573 if (!proto || !proto->connect) {
1574 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1575 file, linenum, args[0], args[1]);
1576 err_code |= ERR_ALERT | ERR_FATAL;
1577 goto out;
1578 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001579
1580 if (port1 != port2) {
1581 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1582 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001583 err_code |= ERR_ALERT | ERR_FATAL;
1584 goto out;
1585 }
1586
Willy Tarreau2aa38802013-02-20 19:20:59 +01001587 if (!port1) {
1588 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1589 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001590 err_code |= ERR_ALERT | ERR_FATAL;
1591 goto out;
1592 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001593
Emeric Brun32da3c42010-09-23 18:39:19 +02001594 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001595 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001596 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001597 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001598
Emeric Brun32da3c42010-09-23 18:39:19 +02001599 if (strcmp(newpeer->id, localpeer) == 0) {
1600 /* Current is local peer, it define a frontend */
1601 newpeer->local = 1;
1602
1603 if (!curpeers->peers_fe) {
1604 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1605 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1606 err_code |= ERR_ALERT | ERR_ABORT;
1607 goto out;
1608 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001609
Willy Tarreau237250c2011-07-29 01:49:03 +02001610 init_new_proxy(curpeers->peers_fe);
1611 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001612
1613 curpeers->peers_fe->last_change = now.tv_sec;
1614 curpeers->peers_fe->id = strdup(args[1]);
1615 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001616 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001617 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1618 curpeers->peers_fe->timeout.connect = 5000;
1619 curpeers->peers_fe->accept = peer_accept;
1620 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001621 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1622 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001623
1624 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1625
Willy Tarreau902636f2013-03-10 19:44:48 +01001626 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1627 if (errmsg && *errmsg) {
1628 indent_msg(&errmsg, 2);
1629 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001630 }
1631 else
1632 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1633 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001634 err_code |= ERR_FATAL;
1635 goto out;
1636 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001637
1638 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
1639 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1640 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1641 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1642 l->accept = session_accept;
1643 l->handler = process_session;
1644 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1645 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1646 global.maxsock += l->maxconn;
1647 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001648 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001649 else {
1650 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1651 file, linenum, args[0], args[1],
1652 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1653 err_code |= ERR_FATAL;
1654 goto out;
1655 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001656 }
1657 } /* neither "peer" nor "peers" */
1658 else if (*args[0] != 0) {
1659 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1660 err_code |= ERR_ALERT | ERR_FATAL;
1661 goto out;
1662 }
1663
1664out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001665 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001666 return err_code;
1667}
1668
Simon Horman69d29f92013-02-23 15:14:19 +09001669static int init_check(struct check *check, int type, const char * file, int linenum)
1670{
1671 check->type = type;
1672
1673 /* Allocate buffer for requests... */
1674 if ((check->bi = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1675 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1676 return ERR_ALERT | ERR_ABORT;
1677 }
1678 check->bi->size = global.tune.chksize;
1679
1680 /* Allocate buffer for responses... */
1681 if ((check->bo = calloc(sizeof(struct buffer) + global.tune.chksize, sizeof(char))) == NULL) {
1682 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
1683 return ERR_ALERT | ERR_ABORT;
1684 }
1685 check->bo->size = global.tune.chksize;
1686
1687 /* Allocate buffer for partial results... */
1688 if ((check->conn = calloc(1, sizeof(struct connection))) == NULL) {
1689 Alert("parsing [%s:%d] : out of memory while allocating check connection.\n", file, linenum);
1690 return ERR_ALERT | ERR_ABORT;
1691 }
1692
1693 check->conn->t.sock.fd = -1; /* no agent in progress yet */
1694
1695 return 0;
1696}
Emeric Brun32da3c42010-09-23 18:39:19 +02001697
Willy Tarreau3842f002009-06-14 11:39:52 +02001698int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699{
1700 static struct proxy *curproxy = NULL;
1701 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001702 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001703 int rc;
1704 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001705 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001706 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001707 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001708 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001709 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711 if (!strcmp(args[0], "listen"))
1712 rc = PR_CAP_LISTEN;
1713 else if (!strcmp(args[0], "frontend"))
1714 rc = PR_CAP_FE | PR_CAP_RS;
1715 else if (!strcmp(args[0], "backend"))
1716 rc = PR_CAP_BE | PR_CAP_RS;
1717 else if (!strcmp(args[0], "ruleset"))
1718 rc = PR_CAP_RS;
1719 else
1720 rc = PR_CAP_NONE;
1721
1722 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 if (!*args[1]) {
1724 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1725 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1726 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001727 err_code |= ERR_ALERT | ERR_ABORT;
1728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001730
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001731 err = invalid_char(args[1]);
1732 if (err) {
1733 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1734 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001735 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001736 }
1737
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001738 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1739 /*
1740 * If there are two proxies with the same name only following
1741 * combinations are allowed:
1742 *
1743 * listen backend frontend ruleset
1744 * listen - - - -
1745 * backend - - OK -
1746 * frontend - OK - -
1747 * ruleset - - - -
1748 */
1749
1750 if (!strcmp(curproxy->id, args[1]) &&
1751 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1752 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001753 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1754 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1755 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001756 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001757 }
1758 }
1759
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1761 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001762 err_code |= ERR_ALERT | ERR_ABORT;
1763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001765
Willy Tarreau97cb7802010-01-03 20:23:58 +01001766 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 curproxy->next = proxy;
1768 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001769 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1770 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001771 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001773 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774
1775 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001776 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001777 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001778
Willy Tarreau4348fad2012-09-20 16:48:07 +02001779 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1780
Willy Tarreau902636f2013-03-10 19:44:48 +01001781 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1782 if (errmsg && *errmsg) {
1783 indent_msg(&errmsg, 2);
1784 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001785 }
1786 else
1787 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1788 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001789 err_code |= ERR_FATAL;
1790 goto out;
1791 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001792
Willy Tarreau4348fad2012-09-20 16:48:07 +02001793 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001794 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001795 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
1797
1798 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001799 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001800 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001801
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001804 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001805 curproxy->no_options = defproxy.no_options;
1806 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001807 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001808 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001809 curproxy->except_net = defproxy.except_net;
1810 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001811 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001812 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001814 if (defproxy.fwdfor_hdr_len) {
1815 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1816 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1817 }
1818
Willy Tarreaub86db342009-11-30 11:50:16 +01001819 if (defproxy.orgto_hdr_len) {
1820 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1821 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1822 }
1823
Mark Lamourinec2247f02012-01-04 13:02:01 -05001824 if (defproxy.server_id_hdr_len) {
1825 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1826 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1827 }
1828
Willy Tarreau977b8e42006-12-29 14:19:17 +01001829 if (curproxy->cap & PR_CAP_FE) {
1830 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001831 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001832 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001833
1834 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001835 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1836 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001837
1838 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1839 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001840
Willy Tarreau977b8e42006-12-29 14:19:17 +01001841 if (curproxy->cap & PR_CAP_BE) {
1842 curproxy->fullconn = defproxy.fullconn;
1843 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001845 if (defproxy.check_req) {
1846 curproxy->check_req = calloc(1, defproxy.check_len);
1847 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1848 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001849 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001850
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001851 if (defproxy.expect_str) {
1852 curproxy->expect_str = strdup(defproxy.expect_str);
1853 if (defproxy.expect_regex) {
1854 /* note: this regex is known to be valid */
1855 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1856 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1857 }
1858 }
1859
Willy Tarreau67402132012-05-31 20:40:20 +02001860 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001861 if (defproxy.cookie_name)
1862 curproxy->cookie_name = strdup(defproxy.cookie_name);
1863 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001864 if (defproxy.cookie_domain)
1865 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001866
Willy Tarreau31936852010-10-06 16:59:56 +02001867 if (defproxy.cookie_maxidle)
1868 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1869
1870 if (defproxy.cookie_maxlife)
1871 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1872
Emeric Brun647caf12009-06-30 17:57:00 +02001873 if (defproxy.rdp_cookie_name)
1874 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1875 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1876
Willy Tarreau01732802007-11-01 22:48:15 +01001877 if (defproxy.url_param_name)
1878 curproxy->url_param_name = strdup(defproxy.url_param_name);
1879 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001880
Benoitaffb4812009-03-25 13:02:10 +01001881 if (defproxy.hh_name)
1882 curproxy->hh_name = strdup(defproxy.hh_name);
1883 curproxy->hh_len = defproxy.hh_len;
1884 curproxy->hh_match_domain = defproxy.hh_match_domain;
1885
Willy Tarreauef9a3602012-12-08 22:29:20 +01001886 if (defproxy.conn_src.iface_name)
1887 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
1888 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08001889 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02001890#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08001891 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02001892#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01001893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001894
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001895 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001896 if (defproxy.capture_name)
1897 curproxy->capture_name = strdup(defproxy.capture_name);
1898 curproxy->capture_namelen = defproxy.capture_namelen;
1899 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901
Willy Tarreau977b8e42006-12-29 14:19:17 +01001902 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001903 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001904 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001905 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001906 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001907 curproxy->uri_auth = defproxy.uri_auth;
1908 curproxy->mon_net = defproxy.mon_net;
1909 curproxy->mon_mask = defproxy.mon_mask;
1910 if (defproxy.monitor_uri)
1911 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1912 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001913 if (defproxy.defbe.name)
1914 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02001915
1916 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02001917 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
1918 if (curproxy->conf.logformat_string &&
1919 curproxy->conf.logformat_string != default_http_log_format &&
1920 curproxy->conf.logformat_string != default_tcp_log_format &&
1921 curproxy->conf.logformat_string != clf_http_log_format)
1922 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
1923
1924 if (defproxy.conf.lfs_file) {
1925 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
1926 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
1927 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001928 }
1929
1930 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001931 curproxy->timeout.connect = defproxy.timeout.connect;
1932 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001933 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001934 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001935 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001936 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001937 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02001938 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01001939 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940 }
1941
Willy Tarreaubaaee002006-06-26 02:48:02 +02001942 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001943
1944 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001945 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001946 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001947 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001948 LIST_INIT(&node->list);
1949 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1950 }
1951
Willy Tarreau62a61232013-04-12 18:13:46 +02001952 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
1953 if (curproxy->conf.uniqueid_format_string)
1954 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
1955
1956 if (defproxy.conf.uif_file) {
1957 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
1958 curproxy->conf.uif_line = defproxy.conf.uif_line;
1959 }
William Lallemanda73203e2012-03-12 12:48:57 +01001960
1961 /* copy default header unique id */
1962 if (defproxy.header_unique_id)
1963 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1964
William Lallemand82fe75c2012-10-23 10:25:10 +02001965 /* default compression options */
1966 if (defproxy.comp != NULL) {
1967 curproxy->comp = calloc(1, sizeof(struct comp));
1968 curproxy->comp->algos = defproxy.comp->algos;
1969 curproxy->comp->types = defproxy.comp->types;
1970 }
1971
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001973 curproxy->conf.used_listener_id = EB_ROOT;
1974 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001975
Willy Tarreau93893792009-07-23 13:19:11 +02001976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977 }
1978 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1979 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001980 /* FIXME-20070101: we should do this too at the end of the
1981 * config parsing to free all default values.
1982 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001983 free(defproxy.check_req);
1984 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001985 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001986 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001987 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001988 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001989 free(defproxy.capture_name);
1990 free(defproxy.monitor_uri);
1991 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01001992 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001993 free(defproxy.fwdfor_hdr_name);
1994 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001995 free(defproxy.orgto_hdr_name);
1996 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001997 free(defproxy.server_id_hdr_name);
1998 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001999 free(defproxy.expect_str);
2000 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01002001
Willy Tarreau62a61232013-04-12 18:13:46 +02002002 if (defproxy.conf.logformat_string != default_http_log_format &&
2003 defproxy.conf.logformat_string != default_tcp_log_format &&
2004 defproxy.conf.logformat_string != clf_http_log_format)
2005 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002006
Willy Tarreau62a61232013-04-12 18:13:46 +02002007 free(defproxy.conf.uniqueid_format_string);
2008 free(defproxy.conf.lfs_file);
2009 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002010
Willy Tarreaua534fea2008-08-03 12:19:50 +02002011 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002012 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002013
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 /* we cannot free uri_auth because it might already be used */
2015 init_default_instance();
2016 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002017 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2018 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002019 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021 }
2022 else if (curproxy == NULL) {
2023 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002024 err_code |= ERR_ALERT | ERR_FATAL;
2025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002026 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002027
2028 /* update the current file and line being parsed */
2029 curproxy->conf.args.file = curproxy->conf.file;
2030 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002031
2032 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002034 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002035 int cur_arg;
2036
Willy Tarreaubaaee002006-06-26 02:48:02 +02002037 if (curproxy == &defproxy) {
2038 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002039 err_code |= ERR_ALERT | ERR_FATAL;
2040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002042 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002043 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044
Willy Tarreau24709282013-03-10 21:32:12 +01002045 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002046 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002051
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002052 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002053
2054 /* use default settings for unix sockets */
2055 bind_conf->ux.uid = global.unix_bind.ux.uid;
2056 bind_conf->ux.gid = global.unix_bind.ux.gid;
2057 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002058
2059 /* NOTE: the following line might create several listeners if there
2060 * are comma-separated IPs or port ranges. So all further processing
2061 * will have to be applied to all listeners created after last_listen.
2062 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002063 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2064 if (errmsg && *errmsg) {
2065 indent_msg(&errmsg, 2);
2066 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002067 }
2068 else
2069 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2070 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002074
Willy Tarreau4348fad2012-09-20 16:48:07 +02002075 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2076 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002077 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002078 }
2079
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002080 cur_arg = 2;
2081 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002082 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002083 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002084 char *err;
2085
Willy Tarreau26982662012-09-12 23:17:10 +02002086 kw = bind_find_kw(args[cur_arg]);
2087 if (kw) {
2088 char *err = NULL;
2089 int code;
2090
2091 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002092 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2093 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002094 cur_arg += 1 + kw->skip ;
2095 err_code |= ERR_ALERT | ERR_FATAL;
2096 goto out;
2097 }
2098
Willy Tarreau4348fad2012-09-20 16:48:07 +02002099 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002100 err_code |= code;
2101
2102 if (code) {
2103 if (err && *err) {
2104 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002105 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002106 }
2107 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002108 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2109 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002110 if (code & ERR_FATAL) {
2111 free(err);
2112 cur_arg += 1 + kw->skip;
2113 goto out;
2114 }
2115 }
2116 free(err);
2117 cur_arg += 1 + kw->skip;
2118 continue;
2119 }
2120
Willy Tarreau8638f482012-09-18 18:01:17 +02002121 err = NULL;
2122 if (!bind_dumped) {
2123 bind_dump_kws(&err);
2124 indent_msg(&err, 4);
2125 bind_dumped = 1;
2126 }
2127
2128 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2129 file, linenum, args[0], args[1], args[cur_arg],
2130 err ? " Registered keywords :" : "", err ? err : "");
2131 free(err);
2132
Willy Tarreau93893792009-07-23 13:19:11 +02002133 err_code |= ERR_ALERT | ERR_FATAL;
2134 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002135 }
Willy Tarreau93893792009-07-23 13:19:11 +02002136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 }
2138 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
2139 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
2140 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2141 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002142 err_code |= ERR_ALERT | ERR_FATAL;
2143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002144 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002145 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002146 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002147
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 /* flush useless bits */
2149 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002151 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002152 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002153 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002154 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002155
Willy Tarreau1c47f852006-07-09 08:22:27 +02002156 if (!*args[1]) {
2157 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2158 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002159 err_code |= ERR_ALERT | ERR_FATAL;
2160 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002161 }
2162
Willy Tarreaua534fea2008-08-03 12:19:50 +02002163 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002164 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002165 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002166 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002167 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2168
Willy Tarreau93893792009-07-23 13:19:11 +02002169 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2172 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2173 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2174 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2175 else {
2176 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002177 err_code |= ERR_ALERT | ERR_FATAL;
2178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002179 }
2180 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002181 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002182 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002183
2184 if (curproxy == &defproxy) {
2185 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002189 }
2190
2191 if (!*args[1]) {
2192 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002194 err_code |= ERR_ALERT | ERR_FATAL;
2195 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002196 }
2197
2198 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002199 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002200
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002201 if (curproxy->uuid <= 0) {
2202 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002203 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002206 }
2207
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002208 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2209 if (node) {
2210 struct proxy *target = container_of(node, struct proxy, conf.id);
2211 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2212 file, linenum, proxy_type_str(curproxy), curproxy->id,
2213 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2214 err_code |= ERR_ALERT | ERR_FATAL;
2215 goto out;
2216 }
2217 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002218 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002219 else if (!strcmp(args[0], "description")) {
2220 int i, len=0;
2221 char *d;
2222
Cyril Bonté99ed3272010-01-24 23:29:44 +01002223 if (curproxy == &defproxy) {
2224 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2225 file, linenum, args[0]);
2226 err_code |= ERR_ALERT | ERR_FATAL;
2227 goto out;
2228 }
2229
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002230 if (!*args[1]) {
2231 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2232 file, linenum, args[0]);
2233 return -1;
2234 }
2235
2236 for(i=1; *args[i]; i++)
2237 len += strlen(args[i])+1;
2238
2239 d = (char *)calloc(1, len);
2240 curproxy->desc = d;
2241
2242 d += sprintf(d, "%s", args[1]);
2243 for(i=2; *args[i]; i++)
2244 d += sprintf(d, " %s", args[i]);
2245
2246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2248 curproxy->state = PR_STSTOPPED;
2249 }
2250 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2251 curproxy->state = PR_STNEW;
2252 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002253 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2254 int cur_arg = 1;
2255 unsigned int set = 0;
2256
2257 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002258 unsigned int low, high;
2259
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002260 if (strcmp(args[cur_arg], "all") == 0) {
2261 set = 0;
2262 break;
2263 }
2264 else if (strcmp(args[cur_arg], "odd") == 0) {
2265 set |= 0x55555555;
2266 }
2267 else if (strcmp(args[cur_arg], "even") == 0) {
2268 set |= 0xAAAAAAAA;
2269 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002270 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002271 char *dash = strchr(args[cur_arg], '-');
2272
2273 low = high = str2uic(args[cur_arg]);
2274 if (dash)
2275 high = str2uic(dash + 1);
2276
2277 if (high < low) {
2278 unsigned int swap = low;
2279 low = high;
2280 high = swap;
2281 }
2282
2283 if (low < 1 || high > 32) {
2284 Alert("parsing [%s:%d]: %s supports process numbers from 1 to 32.\n",
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002285 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002288 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002289
2290 if (high > global.nbproc) {
2291 Warning("parsing [%s:%d]: %s references process number %d which is higher than global.nbproc (%d).\n",
2292 file, linenum, args[0], high, global.nbproc);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002294 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002295 while (low <= high)
2296 set |= 1 << (low++ - 1);
2297 }
2298 else {
2299 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to 32.\n",
2300 file, linenum, args[0]);
2301 err_code |= ERR_ALERT | ERR_FATAL;
2302 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002303 }
2304 cur_arg++;
2305 }
2306 curproxy->bind_proc = set;
2307 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002308 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002309 if (curproxy == &defproxy) {
2310 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002313 }
2314
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002315 err = invalid_char(args[1]);
2316 if (err) {
2317 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2318 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002319 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002320 }
2321
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002322 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002323 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2324 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002325 err_code |= ERR_ALERT | ERR_FATAL;
2326 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002327 }
2328 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2330 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002331
Willy Tarreau977b8e42006-12-29 14:19:17 +01002332 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002334
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 if (*(args[1]) == 0) {
2336 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2337 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002338 err_code |= ERR_ALERT | ERR_FATAL;
2339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002341
Willy Tarreau67402132012-05-31 20:40:20 +02002342 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002343 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002344 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002345 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 curproxy->cookie_name = strdup(args[1]);
2347 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002348
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 cur_arg = 2;
2350 while (*(args[cur_arg])) {
2351 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002352 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002355 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
2357 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002358 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 }
2360 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002361 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
2363 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002364 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002365 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002366 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002367 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002368 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002370 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002372 else if (!strcmp(args[cur_arg], "httponly")) {
2373 curproxy->ck_opts |= PR_CK_HTTPONLY;
2374 }
2375 else if (!strcmp(args[cur_arg], "secure")) {
2376 curproxy->ck_opts |= PR_CK_SECURE;
2377 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002378 else if (!strcmp(args[cur_arg], "domain")) {
2379 if (!*args[cur_arg + 1]) {
2380 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2381 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002384 }
2385
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002386 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002387 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002388 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2389 " dots nor does not start with a dot."
2390 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002391 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002392 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002393 }
2394
2395 err = invalid_domainchar(args[cur_arg + 1]);
2396 if (err) {
2397 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2398 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002401 }
2402
Willy Tarreau68a897b2009-12-03 23:28:34 +01002403 if (!curproxy->cookie_domain) {
2404 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2405 } else {
2406 /* one domain was already specified, add another one by
2407 * building the string which will be returned along with
2408 * the cookie.
2409 */
2410 char *new_ptr;
2411 int new_len = strlen(curproxy->cookie_domain) +
2412 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2413 new_ptr = malloc(new_len);
2414 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2415 free(curproxy->cookie_domain);
2416 curproxy->cookie_domain = new_ptr;
2417 }
Willy Tarreau31936852010-10-06 16:59:56 +02002418 cur_arg++;
2419 }
2420 else if (!strcmp(args[cur_arg], "maxidle")) {
2421 unsigned int maxidle;
2422 const char *res;
2423
2424 if (!*args[cur_arg + 1]) {
2425 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2426 file, linenum, args[cur_arg]);
2427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
2429 }
2430
2431 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2432 if (res) {
2433 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2434 file, linenum, *res, args[cur_arg]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 curproxy->cookie_maxidle = maxidle;
2439 cur_arg++;
2440 }
2441 else if (!strcmp(args[cur_arg], "maxlife")) {
2442 unsigned int maxlife;
2443 const char *res;
2444
2445 if (!*args[cur_arg + 1]) {
2446 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2447 file, linenum, args[cur_arg]);
2448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
2450 }
2451
2452 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2453 if (res) {
2454 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2455 file, linenum, *res, args[cur_arg]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
2459 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002460 cur_arg++;
2461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002462 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002463 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 +02002464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }
2468 cur_arg++;
2469 }
Willy Tarreau67402132012-05-31 20:40:20 +02002470 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2472 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002473 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002474 }
2475
Willy Tarreau67402132012-05-31 20:40:20 +02002476 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002477 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2478 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002481
Willy Tarreau67402132012-05-31 20:40:20 +02002482 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002483 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2484 file, linenum);
2485 err_code |= ERR_ALERT | ERR_FATAL;
2486 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002488 else if (!strcmp(args[0], "persist")) { /* persist */
2489 if (*(args[1]) == 0) {
2490 Alert("parsing [%s:%d] : missing persist method.\n",
2491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002494 }
2495
2496 if (!strncmp(args[1], "rdp-cookie", 10)) {
2497 curproxy->options2 |= PR_O2_RDPC_PRST;
2498
Emeric Brunb982a3d2010-01-04 15:45:53 +01002499 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002500 const char *beg, *end;
2501
2502 beg = args[1] + 11;
2503 end = strchr(beg, ')');
2504
2505 if (!end || end == beg) {
2506 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2507 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002508 err_code |= ERR_ALERT | ERR_FATAL;
2509 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002510 }
2511
2512 free(curproxy->rdp_cookie_name);
2513 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2514 curproxy->rdp_cookie_len = end-beg;
2515 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002516 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002517 free(curproxy->rdp_cookie_name);
2518 curproxy->rdp_cookie_name = strdup("msts");
2519 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2520 }
2521 else { /* syntax */
2522 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2523 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002526 }
2527 }
2528 else {
2529 Alert("parsing [%s:%d] : unknown persist method.\n",
2530 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002531 err_code |= ERR_ALERT | ERR_FATAL;
2532 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002533 }
2534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002535 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002536 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002538 if (curproxy == &defproxy) {
2539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2540 err_code |= ERR_ALERT | ERR_FATAL;
2541 goto out;
2542 }
2543
Willy Tarreau977b8e42006-12-29 14:19:17 +01002544 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002545 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002546
Willy Tarreaubaaee002006-06-26 02:48:02 +02002547 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002548 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
2553 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002554 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555 curproxy->appsession_name = strdup(args[1]);
2556 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2557 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002558 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2559 if (err) {
2560 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2561 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_ALERT | ERR_FATAL;
2563 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002564 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002565 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002566
Willy Tarreau51041c72007-09-09 21:56:53 +02002567 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2568 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002569 err_code |= ERR_ALERT | ERR_ABORT;
2570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002572
2573 cur_arg = 6;
2574 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002575 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2576 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002577 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002578 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002579 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002580 } else if (!strcmp(args[cur_arg], "prefix")) {
2581 curproxy->options2 |= PR_O2_AS_PFX;
2582 } else if (!strcmp(args[cur_arg], "mode")) {
2583 if (!*args[cur_arg + 1]) {
2584 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2585 file, linenum, args[0], args[cur_arg]);
2586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
2588 }
2589
2590 cur_arg++;
2591 if (!strcmp(args[cur_arg], "query-string")) {
2592 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2593 curproxy->options2 |= PR_O2_AS_M_QS;
2594 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2595 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2596 curproxy->options2 |= PR_O2_AS_M_PP;
2597 } else {
2598 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
2602 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002603 cur_arg++;
2604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 } /* Url App Session */
2606 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002607 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002608 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002609
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002611 if (curproxy == &defproxy) {
2612 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
2615 }
2616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (*(args[4]) == 0) {
2618 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2619 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002623 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 curproxy->capture_name = strdup(args[2]);
2625 curproxy->capture_namelen = strlen(curproxy->capture_name);
2626 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 curproxy->to_log |= LW_COOKIE;
2628 }
2629 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2630 struct cap_hdr *hdr;
2631
2632 if (curproxy == &defproxy) {
2633 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 +02002634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002636 }
2637
2638 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2639 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2640 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 }
2644
2645 hdr = calloc(sizeof(struct cap_hdr), 1);
2646 hdr->next = curproxy->req_cap;
2647 hdr->name = strdup(args[3]);
2648 hdr->namelen = strlen(args[3]);
2649 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002650 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002651 hdr->index = curproxy->nb_req_cap++;
2652 curproxy->req_cap = hdr;
2653 curproxy->to_log |= LW_REQHDR;
2654 }
2655 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2656 struct cap_hdr *hdr;
2657
2658 if (curproxy == &defproxy) {
2659 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 +02002660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002662 }
2663
2664 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2665 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2666 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002669 }
2670 hdr = calloc(sizeof(struct cap_hdr), 1);
2671 hdr->next = curproxy->rsp_cap;
2672 hdr->name = strdup(args[3]);
2673 hdr->namelen = strlen(args[3]);
2674 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002675 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 hdr->index = curproxy->nb_rsp_cap++;
2677 curproxy->rsp_cap = hdr;
2678 curproxy->to_log |= LW_RSPHDR;
2679 }
2680 else {
2681 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2682 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 }
2686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002688 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002690
Willy Tarreaubaaee002006-06-26 02:48:02 +02002691 if (*(args[1]) == 0) {
2692 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2693 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 }
2697 curproxy->conn_retries = atol(args[1]);
2698 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002699 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002700 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002701
2702 if (curproxy == &defproxy) {
2703 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
2706 }
2707
Willy Tarreau20b0de52012-12-24 15:45:22 +01002708 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2709 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2710 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2711 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002712 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002713 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2714 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 +01002715 file, linenum, args[0]);
2716 err_code |= ERR_WARN;
2717 }
2718
Willy Tarreauff011f22011-01-06 17:51:27 +01002719 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002720
Willy Tarreauff011f22011-01-06 17:51:27 +01002721 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002722 err_code |= ERR_ALERT | ERR_ABORT;
2723 goto out;
2724 }
2725
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002726 err_code |= warnif_cond_conflicts(rule->cond,
2727 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2728 file, linenum);
2729
Willy Tarreauff011f22011-01-06 17:51:27 +01002730 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002731 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002732 else if (!strcmp(args[0], "http-response")) { /* response access control */
2733 struct http_res_rule *rule;
2734
2735 if (curproxy == &defproxy) {
2736 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2742 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2743 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2744 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2745 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2746 file, linenum, args[0]);
2747 err_code |= ERR_WARN;
2748 }
2749
2750 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2751
2752 if (!rule) {
2753 err_code |= ERR_ALERT | ERR_ABORT;
2754 goto out;
2755 }
2756
2757 err_code |= warnif_cond_conflicts(rule->cond,
2758 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2759 file, linenum);
2760
2761 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2762 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002763 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2764 /* set the header name and length into the proxy structure */
2765 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2766 err_code |= ERR_WARN;
2767
2768 if (!*args[1]) {
2769 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2770 file, linenum, args[0]);
2771 err_code |= ERR_ALERT | ERR_FATAL;
2772 goto out;
2773 }
2774
2775 /* set the desired header name */
2776 free(curproxy->server_id_hdr_name);
2777 curproxy->server_id_hdr_name = strdup(args[1]);
2778 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2779 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002780 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002781 if (curproxy == &defproxy) {
2782 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_ALERT | ERR_FATAL;
2784 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002785 }
2786
Willy Tarreauef6494c2010-01-28 17:12:36 +01002787 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002788 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2789 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002790 err_code |= ERR_ALERT | ERR_FATAL;
2791 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002792 }
2793
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002794 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2795 Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n",
2796 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002797 err_code |= ERR_ALERT | ERR_FATAL;
2798 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002799 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002800
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002801 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002802 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002803 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002804 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002805 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002806
Cyril Bonté99ed3272010-01-24 23:29:44 +01002807 if (curproxy == &defproxy) {
2808 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
2812
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002813 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01002814 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
2815 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002818 }
2819
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002820 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002821 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002822 err_code |= warnif_cond_conflicts(rule->cond,
2823 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2824 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002825 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002826 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002827 struct switching_rule *rule;
2828
Willy Tarreaub099aca2008-10-12 17:26:37 +02002829 if (curproxy == &defproxy) {
2830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_ALERT | ERR_FATAL;
2832 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002833 }
2834
Willy Tarreau55ea7572007-06-17 19:56:27 +02002835 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002836 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002837
2838 if (*(args[1]) == 0) {
2839 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002842 }
2843
Willy Tarreauef6494c2010-01-28 17:12:36 +01002844 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002845 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2846 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002849 }
2850
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002851 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2852 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2853 file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002854 err_code |= ERR_ALERT | ERR_FATAL;
2855 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002856 }
2857
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002858 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002859
Willy Tarreau55ea7572007-06-17 19:56:27 +02002860 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2861 rule->cond = cond;
2862 rule->be.name = strdup(args[1]);
2863 LIST_INIT(&rule->list);
2864 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2865 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002866 else if (strcmp(args[0], "use-server") == 0) {
2867 struct server_rule *rule;
2868
2869 if (curproxy == &defproxy) {
2870 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
2873 }
2874
2875 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2876 err_code |= ERR_WARN;
2877
2878 if (*(args[1]) == 0) {
2879 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
2882 }
2883
2884 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2885 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2886 file, linenum, args[0]);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002891 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2892 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
2893 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
2897
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002898 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002899
2900 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2901 rule->cond = cond;
2902 rule->srv.name = strdup(args[1]);
2903 LIST_INIT(&rule->list);
2904 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2905 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2906 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002907 else if ((!strcmp(args[0], "force-persist")) ||
2908 (!strcmp(args[0], "ignore-persist"))) {
2909 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002910
2911 if (curproxy == &defproxy) {
2912 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916
2917 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2918 err_code |= ERR_WARN;
2919
Willy Tarreauef6494c2010-01-28 17:12:36 +01002920 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002921 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2922 file, linenum, args[0]);
2923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
2925 }
2926
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002927 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
2928 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
2929 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01002930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002934 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
2935 * where force-persist is applied.
2936 */
2937 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002938
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002939 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002940 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002941 if (!strcmp(args[0], "force-persist")) {
2942 rule->type = PERSIST_TYPE_FORCE;
2943 } else {
2944 rule->type = PERSIST_TYPE_IGNORE;
2945 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002946 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002947 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002948 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002949 else if (!strcmp(args[0], "stick-table")) {
2950 int myidx = 1;
2951
Emeric Brun32da3c42010-09-23 18:39:19 +02002952 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 curproxy->table.type = (unsigned int)-1;
2954 while (*args[myidx]) {
2955 const char *err;
2956
2957 if (strcmp(args[myidx], "size") == 0) {
2958 myidx++;
2959 if (!*(args[myidx])) {
2960 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2961 file, linenum, args[myidx-1]);
2962 err_code |= ERR_ALERT | ERR_FATAL;
2963 goto out;
2964 }
2965 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2966 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2967 file, linenum, *err, args[myidx-1]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002971 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002972 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002973 else if (strcmp(args[myidx], "peers") == 0) {
2974 myidx++;
Godbach50523162013-12-11 19:48:57 +08002975 if (!*(args[myidx])) {
2976 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2977 file, linenum, args[myidx-1]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002981 curproxy->table.peers.name = strdup(args[myidx++]);
2982 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002983 else if (strcmp(args[myidx], "expire") == 0) {
2984 myidx++;
2985 if (!*(args[myidx])) {
2986 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2987 file, linenum, args[myidx-1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2992 if (err) {
2993 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2994 file, linenum, *err, args[myidx-1]);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002999 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003000 }
3001 else if (strcmp(args[myidx], "nopurge") == 0) {
3002 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003003 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003004 }
3005 else if (strcmp(args[myidx], "type") == 0) {
3006 myidx++;
3007 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3008 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3009 file, linenum, args[myidx]);
3010 err_code |= ERR_ALERT | ERR_FATAL;
3011 goto out;
3012 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003013 /* myidx already points to next arg */
3014 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003015 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003016 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003017 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003018
3019 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003020 nw = args[myidx];
3021 while (*nw) {
3022 /* the "store" keyword supports a comma-separated list */
3023 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003024 sa = NULL; /* store arg */
3025 while (*nw && *nw != ',') {
3026 if (*nw == '(') {
3027 *nw = 0;
3028 sa = ++nw;
3029 while (*nw != ')') {
3030 if (!*nw) {
3031 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3032 file, linenum, args[0], cw);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
3035 }
3036 nw++;
3037 }
3038 *nw = '\0';
3039 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003040 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003041 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003042 if (*nw)
3043 *nw++ = '\0';
3044 type = stktable_get_data_type(cw);
3045 if (type < 0) {
3046 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3047 file, linenum, args[0], cw);
3048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
3050 }
Willy Tarreauac782882010-06-20 10:41:54 +02003051
3052 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3053 switch (err) {
3054 case PE_NONE: break;
3055 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003056 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3057 file, linenum, args[0], cw);
3058 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003059 break;
3060
3061 case PE_ARG_MISSING:
3062 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3063 file, linenum, args[0], cw);
3064 err_code |= ERR_ALERT | ERR_FATAL;
3065 goto out;
3066
3067 case PE_ARG_NOT_USED:
3068 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3069 file, linenum, args[0], cw);
3070 err_code |= ERR_ALERT | ERR_FATAL;
3071 goto out;
3072
3073 default:
3074 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3075 file, linenum, args[0], cw);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003078 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003079 }
3080 myidx++;
3081 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003082 else {
3083 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3084 file, linenum, args[myidx]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003087 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003088 }
3089
3090 if (!curproxy->table.size) {
3091 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3092 file, linenum);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096
3097 if (curproxy->table.type == (unsigned int)-1) {
3098 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3099 file, linenum);
3100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
3102 }
3103 }
3104 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003105 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003106 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003107 int myidx = 0;
3108 const char *name = NULL;
3109 int flags;
3110
3111 if (curproxy == &defproxy) {
3112 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
3116
3117 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3118 err_code |= ERR_WARN;
3119 goto out;
3120 }
3121
3122 myidx++;
3123 if ((strcmp(args[myidx], "store") == 0) ||
3124 (strcmp(args[myidx], "store-request") == 0)) {
3125 myidx++;
3126 flags = STK_IS_STORE;
3127 }
3128 else if (strcmp(args[myidx], "store-response") == 0) {
3129 myidx++;
3130 flags = STK_IS_STORE | STK_ON_RSP;
3131 }
3132 else if (strcmp(args[myidx], "match") == 0) {
3133 myidx++;
3134 flags = STK_IS_MATCH;
3135 }
3136 else if (strcmp(args[myidx], "on") == 0) {
3137 myidx++;
3138 flags = STK_IS_MATCH | STK_IS_STORE;
3139 }
3140 else {
3141 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
3144 }
3145
3146 if (*(args[myidx]) == 0) {
3147 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
3150 }
3151
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003152 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreau975c1782013-12-12 23:16:54 +01003153 expr = sample_parse_expr(args, &myidx, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003155 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
3158 }
3159
3160 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003161 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3162 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3163 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003164 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003165 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003166 goto out;
3167 }
3168 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003169 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3170 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3171 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003172 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003173 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003174 goto out;
3175 }
3176 }
3177
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003178 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003179 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003180
Emeric Brunb982a3d2010-01-04 15:45:53 +01003181 if (strcmp(args[myidx], "table") == 0) {
3182 myidx++;
3183 name = args[myidx++];
3184 }
3185
Willy Tarreauef6494c2010-01-28 17:12:36 +01003186 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003187 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3188 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3189 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003190 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003191 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003192 goto out;
3193 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003194 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003195 else if (*(args[myidx])) {
3196 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3197 file, linenum, args[0], args[myidx]);
3198 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003199 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003200 goto out;
3201 }
Emeric Brun97679e72010-09-23 17:56:44 +02003202 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003203 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003204 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003205 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003206
Emeric Brunb982a3d2010-01-04 15:45:53 +01003207 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3208 rule->cond = cond;
3209 rule->expr = expr;
3210 rule->flags = flags;
3211 rule->table.name = name ? strdup(name) : NULL;
3212 LIST_INIT(&rule->list);
3213 if (flags & STK_ON_RSP)
3214 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3215 else
3216 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003220 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003221
Willy Tarreaubaaee002006-06-26 02:48:02 +02003222 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3223 curproxy->uri_auth = NULL; /* we must detach from the default config */
3224
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003225 if (!*args[1]) {
3226 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003227 } else if (!strcmp(args[1], "admin")) {
3228 struct stats_admin_rule *rule;
3229
3230 if (curproxy == &defproxy) {
3231 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3232 err_code |= ERR_ALERT | ERR_FATAL;
3233 goto out;
3234 }
3235
3236 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3237 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3238 err_code |= ERR_ALERT | ERR_ABORT;
3239 goto out;
3240 }
3241
3242 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3243 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3244 file, linenum, args[0], args[1]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003248 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3249 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3250 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003251 err_code |= ERR_ALERT | ERR_FATAL;
3252 goto out;
3253 }
3254
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003255 err_code |= warnif_cond_conflicts(cond,
3256 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3257 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003258
3259 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3260 rule->cond = cond;
3261 LIST_INIT(&rule->list);
3262 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 } else if (!strcmp(args[1], "uri")) {
3264 if (*(args[2]) == 0) {
3265 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3269 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003270 err_code |= ERR_ALERT | ERR_ABORT;
3271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003272 }
3273 } else if (!strcmp(args[1], "realm")) {
3274 if (*(args[2]) == 0) {
3275 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3279 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003280 err_code |= ERR_ALERT | ERR_ABORT;
3281 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003283 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003284 unsigned interval;
3285
3286 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3287 if (err) {
3288 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3289 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003292 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3293 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003294 err_code |= ERR_ALERT | ERR_ABORT;
3295 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003296 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003297 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003298 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003299
3300 if (curproxy == &defproxy) {
3301 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3302 err_code |= ERR_ALERT | ERR_FATAL;
3303 goto out;
3304 }
3305
3306 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3307 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3308 err_code |= ERR_ALERT | ERR_ABORT;
3309 goto out;
3310 }
3311
Willy Tarreauff011f22011-01-06 17:51:27 +01003312 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3313 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003314 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3315 file, linenum, args[0]);
3316 err_code |= ERR_WARN;
3317 }
3318
Willy Tarreauff011f22011-01-06 17:51:27 +01003319 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003320
Willy Tarreauff011f22011-01-06 17:51:27 +01003321 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003322 err_code |= ERR_ALERT | ERR_ABORT;
3323 goto out;
3324 }
3325
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003326 err_code |= warnif_cond_conflicts(rule->cond,
3327 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3328 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003329 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003330
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 } else if (!strcmp(args[1], "auth")) {
3332 if (*(args[2]) == 0) {
3333 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003334 err_code |= ERR_ALERT | ERR_FATAL;
3335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003336 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3337 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_ABORT;
3339 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003340 }
3341 } else if (!strcmp(args[1], "scope")) {
3342 if (*(args[2]) == 0) {
3343 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
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;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 }
3351 } else if (!strcmp(args[1], "enable")) {
3352 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3353 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003354 err_code |= ERR_ALERT | ERR_ABORT;
3355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003357 } else if (!strcmp(args[1], "hide-version")) {
3358 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003360 err_code |= ERR_ALERT | ERR_ABORT;
3361 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003362 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003363 } else if (!strcmp(args[1], "show-legends")) {
3364 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3365 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3366 err_code |= ERR_ALERT | ERR_ABORT;
3367 goto out;
3368 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003369 } else if (!strcmp(args[1], "show-node")) {
3370
3371 if (*args[2]) {
3372 int i;
3373 char c;
3374
3375 for (i=0; args[2][i]; i++) {
3376 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003377 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3378 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003379 break;
3380 }
3381
3382 if (!i || args[2][i]) {
3383 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3384 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3385 file, linenum, args[0], args[1]);
3386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
3388 }
3389 }
3390
3391 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3392 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3393 err_code |= ERR_ALERT | ERR_ABORT;
3394 goto out;
3395 }
3396 } else if (!strcmp(args[1], "show-desc")) {
3397 char *desc = NULL;
3398
3399 if (*args[2]) {
3400 int i, len=0;
3401 char *d;
3402
3403 for(i=2; *args[i]; i++)
3404 len += strlen(args[i])+1;
3405
3406 desc = d = (char *)calloc(1, len);
3407
3408 d += sprintf(d, "%s", args[2]);
3409 for(i=3; *args[i]; i++)
3410 d += sprintf(d, " %s", args[i]);
3411 }
3412
3413 if (!*args[2] && !global.desc)
3414 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3415 file, linenum, args[1]);
3416 else {
3417 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3418 free(desc);
3419 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3420 err_code |= ERR_ALERT | ERR_ABORT;
3421 goto out;
3422 }
3423 free(desc);
3424 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003426stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003427 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 +01003428 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
3432 }
3433 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003434 int optnum;
3435
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003436 if (*(args[1]) == '\0') {
3437 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3438 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_ALERT | ERR_FATAL;
3440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003442
3443 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3444 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003445 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3446 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3447 file, linenum, cfg_opts[optnum].name);
3448 err_code |= ERR_ALERT | ERR_FATAL;
3449 goto out;
3450 }
Willy Tarreau93893792009-07-23 13:19:11 +02003451 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3452 err_code |= ERR_WARN;
3453 goto out;
3454 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003455
Willy Tarreau3842f002009-06-14 11:39:52 +02003456 curproxy->no_options &= ~cfg_opts[optnum].val;
3457 curproxy->options &= ~cfg_opts[optnum].val;
3458
3459 switch (kwm) {
3460 case KWM_STD:
3461 curproxy->options |= cfg_opts[optnum].val;
3462 break;
3463 case KWM_NO:
3464 curproxy->no_options |= cfg_opts[optnum].val;
3465 break;
3466 case KWM_DEF: /* already cleared */
3467 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003468 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003469
Willy Tarreau93893792009-07-23 13:19:11 +02003470 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003471 }
3472 }
3473
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003474 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3475 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003476 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3477 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3478 file, linenum, cfg_opts2[optnum].name);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
Willy Tarreau93893792009-07-23 13:19:11 +02003482 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3483 err_code |= ERR_WARN;
3484 goto out;
3485 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003486
Willy Tarreau3842f002009-06-14 11:39:52 +02003487 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3488 curproxy->options2 &= ~cfg_opts2[optnum].val;
3489
3490 switch (kwm) {
3491 case KWM_STD:
3492 curproxy->options2 |= cfg_opts2[optnum].val;
3493 break;
3494 case KWM_NO:
3495 curproxy->no_options2 |= cfg_opts2[optnum].val;
3496 break;
3497 case KWM_DEF: /* already cleared */
3498 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003499 }
Willy Tarreau93893792009-07-23 13:19:11 +02003500 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003501 }
3502 }
3503
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003504 /* HTTP options override each other. They can be cancelled using
3505 * "no option xxx" which only switches to default mode if the mode
3506 * was this one (useful for cancelling options set in defaults
3507 * sections).
3508 */
3509 if (strcmp(args[1], "httpclose") == 0) {
3510 if (kwm == KWM_STD) {
3511 curproxy->options &= ~PR_O_HTTP_MODE;
3512 curproxy->options |= PR_O_HTTP_PCL;
3513 goto out;
3514 }
3515 else if (kwm == KWM_NO) {
3516 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3517 curproxy->options &= ~PR_O_HTTP_MODE;
3518 goto out;
3519 }
3520 }
3521 else if (strcmp(args[1], "forceclose") == 0) {
3522 if (kwm == KWM_STD) {
3523 curproxy->options &= ~PR_O_HTTP_MODE;
3524 curproxy->options |= PR_O_HTTP_FCL;
3525 goto out;
3526 }
3527 else if (kwm == KWM_NO) {
3528 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3529 curproxy->options &= ~PR_O_HTTP_MODE;
3530 goto out;
3531 }
3532 }
3533 else if (strcmp(args[1], "http-server-close") == 0) {
3534 if (kwm == KWM_STD) {
3535 curproxy->options &= ~PR_O_HTTP_MODE;
3536 curproxy->options |= PR_O_HTTP_SCL;
3537 goto out;
3538 }
3539 else if (kwm == KWM_NO) {
3540 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3541 curproxy->options &= ~PR_O_HTTP_MODE;
3542 goto out;
3543 }
3544 }
3545 else if (strcmp(args[1], "http-keep-alive") == 0) {
3546 if (kwm == KWM_STD) {
3547 curproxy->options &= ~PR_O_HTTP_MODE;
3548 curproxy->options |= PR_O_HTTP_KAL;
3549 goto out;
3550 }
3551 else if (kwm == KWM_NO) {
3552 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3553 curproxy->options &= ~PR_O_HTTP_MODE;
3554 goto out;
3555 }
3556 }
3557 else if (strcmp(args[1], "http-tunnel") == 0) {
3558 if (kwm == KWM_STD) {
3559 curproxy->options &= ~PR_O_HTTP_MODE;
3560 curproxy->options |= PR_O_HTTP_TUN;
3561 goto out;
3562 }
3563 else if (kwm == KWM_NO) {
3564 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3565 curproxy->options &= ~PR_O_HTTP_MODE;
3566 goto out;
3567 }
3568 }
3569
Willy Tarreau3842f002009-06-14 11:39:52 +02003570 if (kwm != KWM_STD) {
3571 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003572 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003575 }
3576
Emeric Brun3a058f32009-06-30 18:26:00 +02003577 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003578 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003579 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003580 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003581 if (*(args[2]) != '\0') {
3582 if (!strcmp(args[2], "clf")) {
3583 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003584 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003585 } else {
3586 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003589 }
3590 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003591 if (curproxy->conf.logformat_string != default_http_log_format &&
3592 curproxy->conf.logformat_string != default_tcp_log_format &&
3593 curproxy->conf.logformat_string != clf_http_log_format)
3594 free(curproxy->conf.logformat_string);
3595 curproxy->conf.logformat_string = logformat;
3596
3597 free(curproxy->conf.lfs_file);
3598 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3599 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003600 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003601 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003602 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003603 if (curproxy->conf.logformat_string != default_http_log_format &&
3604 curproxy->conf.logformat_string != default_tcp_log_format &&
3605 curproxy->conf.logformat_string != clf_http_log_format)
3606 free(curproxy->conf.logformat_string);
3607 curproxy->conf.logformat_string = default_tcp_log_format;
3608
3609 free(curproxy->conf.lfs_file);
3610 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3611 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003612 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 else if (!strcmp(args[1], "tcpka")) {
3614 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003615 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003617
3618 if (curproxy->cap & PR_CAP_FE)
3619 curproxy->options |= PR_O_TCP_CLI_KA;
3620 if (curproxy->cap & PR_CAP_BE)
3621 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
3623 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003624 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_WARN;
3626
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003628 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003629 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003630 curproxy->options2 &= ~PR_O2_CHK_ANY;
3631 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003632 if (!*args[2]) { /* no argument */
3633 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3634 curproxy->check_len = strlen(DEF_CHECK_REQ);
3635 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003636 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 curproxy->check_req = (char *)malloc(reqlen);
3638 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003639 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003640 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003641 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 if (*args[4])
3643 reqlen += strlen(args[4]);
3644 else
3645 reqlen += strlen("HTTP/1.0");
3646
3647 curproxy->check_req = (char *)malloc(reqlen);
3648 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003649 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003651 }
3652 else if (!strcmp(args[1], "ssl-hello-chk")) {
3653 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003656
Willy Tarreaua534fea2008-08-03 12:19:50 +02003657 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003658 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003659 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003660 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 }
Willy Tarreau23677902007-05-08 23:50:35 +02003662 else if (!strcmp(args[1], "smtpchk")) {
3663 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003664 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003665 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003666 curproxy->options2 &= ~PR_O2_CHK_ANY;
3667 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003668
3669 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3670 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3671 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3672 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3673 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3674 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3675 curproxy->check_req = (char *)malloc(reqlen);
3676 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3677 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3678 } else {
3679 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3680 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3681 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3682 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3683 }
3684 }
3685 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003686 else if (!strcmp(args[1], "pgsql-check")) {
3687 /* use PostgreSQL request to check servers' health */
3688 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3689 err_code |= ERR_WARN;
3690
3691 free(curproxy->check_req);
3692 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003693 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003694 curproxy->options2 |= PR_O2_PGSQL_CHK;
3695
3696 if (*(args[2])) {
3697 int cur_arg = 2;
3698
3699 while (*(args[cur_arg])) {
3700 if (strcmp(args[cur_arg], "user") == 0) {
3701 char * packet;
3702 uint32_t packet_len;
3703 uint32_t pv;
3704
3705 /* suboption header - needs additional argument for it */
3706 if (*(args[cur_arg+1]) == 0) {
3707 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3708 file, linenum, args[0], args[1], args[cur_arg]);
3709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
3711 }
3712
3713 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3714 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3715 pv = htonl(0x30000); /* protocol version 3.0 */
3716
3717 packet = (char*) calloc(1, packet_len);
3718
3719 memcpy(packet + 4, &pv, 4);
3720
3721 /* copy "user" */
3722 memcpy(packet + 8, "user", 4);
3723
3724 /* copy username */
3725 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3726
3727 free(curproxy->check_req);
3728 curproxy->check_req = packet;
3729 curproxy->check_len = packet_len;
3730
3731 packet_len = htonl(packet_len);
3732 memcpy(packet, &packet_len, 4);
3733 cur_arg += 2;
3734 } else {
3735 /* unknown suboption - catchall */
3736 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3737 file, linenum, args[0], args[1]);
3738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
3740 }
3741 } /* end while loop */
3742 }
3743 }
3744
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003745 else if (!strcmp(args[1], "redis-check")) {
3746 /* use REDIS PING request to check servers' health */
3747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3748 err_code |= ERR_WARN;
3749
3750 free(curproxy->check_req);
3751 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003752 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003753 curproxy->options2 |= PR_O2_REDIS_CHK;
3754
3755 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3756 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3757 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3758 }
3759
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003760 else if (!strcmp(args[1], "mysql-check")) {
3761 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003762 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3763 err_code |= ERR_WARN;
3764
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003765 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003766 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003767 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003768 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003769
3770 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3771 * const char mysql40_client_auth_pkt[] = {
3772 * "\x0e\x00\x00" // packet length
3773 * "\x01" // packet number
3774 * "\x00\x00" // client capabilities
3775 * "\x00\x00\x01" // max packet
3776 * "haproxy\x00" // username (null terminated string)
3777 * "\x00" // filler (always 0x00)
3778 * "\x01\x00\x00" // packet length
3779 * "\x00" // packet number
3780 * "\x01" // COM_QUIT command
3781 * };
3782 */
3783
3784 if (*(args[2])) {
3785 int cur_arg = 2;
3786
3787 while (*(args[cur_arg])) {
3788 if (strcmp(args[cur_arg], "user") == 0) {
3789 char *mysqluser;
3790 int packetlen, reqlen, userlen;
3791
3792 /* suboption header - needs additional argument for it */
3793 if (*(args[cur_arg+1]) == 0) {
3794 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3795 file, linenum, args[0], args[1], args[cur_arg]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799 mysqluser = args[cur_arg + 1];
3800 userlen = strlen(mysqluser);
3801 packetlen = userlen + 7;
3802 reqlen = packetlen + 9;
3803
3804 free(curproxy->check_req);
3805 curproxy->check_req = (char *)calloc(1, reqlen);
3806 curproxy->check_len = reqlen;
3807
3808 snprintf(curproxy->check_req, 4, "%c%c%c",
3809 ((unsigned char) packetlen & 0xff),
3810 ((unsigned char) (packetlen >> 8) & 0xff),
3811 ((unsigned char) (packetlen >> 16) & 0xff));
3812
3813 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003814 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003815 curproxy->check_req[8] = 1;
3816 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3817 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3818 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3819 cur_arg += 2;
3820 } else {
3821 /* unknown suboption - catchall */
3822 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3823 file, linenum, args[0], args[1]);
3824 err_code |= ERR_ALERT | ERR_FATAL;
3825 goto out;
3826 }
3827 } /* end while loop */
3828 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003829 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003830 else if (!strcmp(args[1], "ldap-check")) {
3831 /* use LDAP request to check servers' health */
3832 free(curproxy->check_req);
3833 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003834 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003835 curproxy->options2 |= PR_O2_LDAP_CHK;
3836
3837 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3838 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3839 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3840 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02003841 else if (!strcmp(args[1], "tcp-check")) {
3842 /* use raw TCPCHK send/expect to check servers' health */
3843 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3844 err_code |= ERR_WARN;
3845
3846 free(curproxy->check_req);
3847 curproxy->check_req = NULL;
3848 curproxy->options2 &= ~PR_O2_CHK_ANY;
3849 curproxy->options2 |= PR_O2_TCPCHK_CHK;
3850 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003851 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003852 int cur_arg;
3853
3854 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3855 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003856 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003857
Willy Tarreau87cf5142011-08-19 22:57:24 +02003858 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003859
3860 free(curproxy->fwdfor_hdr_name);
3861 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3862 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3863
3864 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3865 cur_arg = 2;
3866 while (*(args[cur_arg])) {
3867 if (!strcmp(args[cur_arg], "except")) {
3868 /* suboption except - needs additional argument for it */
3869 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3870 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3871 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003874 }
3875 /* flush useless bits */
3876 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003877 cur_arg += 2;
3878 } else if (!strcmp(args[cur_arg], "header")) {
3879 /* suboption header - needs additional argument for it */
3880 if (*(args[cur_arg+1]) == 0) {
3881 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3882 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003885 }
3886 free(curproxy->fwdfor_hdr_name);
3887 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3888 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3889 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003890 } else if (!strcmp(args[cur_arg], "if-none")) {
3891 curproxy->options &= ~PR_O_FF_ALWAYS;
3892 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003893 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003894 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003895 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003896 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003897 err_code |= ERR_ALERT | ERR_FATAL;
3898 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003899 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003900 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003901 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003902 else if (!strcmp(args[1], "originalto")) {
3903 int cur_arg;
3904
3905 /* insert x-original-to field, but not for the IP address listed as an except.
3906 * set default options (ie: bitfield, header name, etc)
3907 */
3908
3909 curproxy->options |= PR_O_ORGTO;
3910
3911 free(curproxy->orgto_hdr_name);
3912 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3913 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3914
Willy Tarreau87cf5142011-08-19 22:57:24 +02003915 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003916 cur_arg = 2;
3917 while (*(args[cur_arg])) {
3918 if (!strcmp(args[cur_arg], "except")) {
3919 /* suboption except - needs additional argument for it */
3920 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3921 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3922 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003923 err_code |= ERR_ALERT | ERR_FATAL;
3924 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003925 }
3926 /* flush useless bits */
3927 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3928 cur_arg += 2;
3929 } else if (!strcmp(args[cur_arg], "header")) {
3930 /* suboption header - needs additional argument for it */
3931 if (*(args[cur_arg+1]) == 0) {
3932 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3933 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003934 err_code |= ERR_ALERT | ERR_FATAL;
3935 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003936 }
3937 free(curproxy->orgto_hdr_name);
3938 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3939 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3940 cur_arg += 2;
3941 } else {
3942 /* unknown suboption - catchall */
3943 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3944 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003947 }
3948 } /* end while loop */
3949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003950 else {
3951 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003954 }
Willy Tarreau93893792009-07-23 13:19:11 +02003955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003956 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003957 else if (!strcmp(args[0], "default_backend")) {
3958 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003959 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003960
3961 if (*(args[1]) == 0) {
3962 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003963 err_code |= ERR_ALERT | ERR_FATAL;
3964 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003965 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003966 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003967 curproxy->defbe.name = strdup(args[1]);
3968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003969 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003970 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003971 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003972
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003973 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3974 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003975 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003976 /* enable reconnections to dispatch */
3977 curproxy->options |= PR_O_REDISP;
3978 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003979 else if (!strcmp(args[0], "http-check")) {
3980 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003981 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003982
3983 if (strcmp(args[1], "disable-on-404") == 0) {
3984 /* enable a graceful server shutdown on an HTTP 404 response */
3985 curproxy->options |= PR_O_DISABLE404;
3986 }
Willy Tarreauef781042010-01-27 11:53:01 +01003987 else if (strcmp(args[1], "send-state") == 0) {
3988 /* enable emission of the apparent state of a server in HTTP checks */
3989 curproxy->options2 |= PR_O2_CHK_SNDST;
3990 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003991 else if (strcmp(args[1], "expect") == 0) {
3992 const char *ptr_arg;
3993 int cur_arg;
3994
3995 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3996 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
3999 }
4000
4001 cur_arg = 2;
4002 /* consider exclamation marks, sole or at the beginning of a word */
4003 while (*(ptr_arg = args[cur_arg])) {
4004 while (*ptr_arg == '!') {
4005 curproxy->options2 ^= PR_O2_EXP_INV;
4006 ptr_arg++;
4007 }
4008 if (*ptr_arg)
4009 break;
4010 cur_arg++;
4011 }
4012 /* now ptr_arg points to the beginning of a word past any possible
4013 * exclamation mark, and cur_arg is the argument which holds this word.
4014 */
4015 if (strcmp(ptr_arg, "status") == 0) {
4016 if (!*(args[cur_arg + 1])) {
4017 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4018 file, linenum, args[0], args[1], ptr_arg);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004023 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004024 curproxy->expect_str = strdup(args[cur_arg + 1]);
4025 }
4026 else if (strcmp(ptr_arg, "string") == 0) {
4027 if (!*(args[cur_arg + 1])) {
4028 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4029 file, linenum, args[0], args[1], ptr_arg);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032 }
4033 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004034 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004035 curproxy->expect_str = strdup(args[cur_arg + 1]);
4036 }
4037 else if (strcmp(ptr_arg, "rstatus") == 0) {
4038 if (!*(args[cur_arg + 1])) {
4039 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4040 file, linenum, args[0], args[1], ptr_arg);
4041 err_code |= ERR_ALERT | ERR_FATAL;
4042 goto out;
4043 }
4044 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004045 free(curproxy->expect_str);
4046 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4047 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004048 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4049 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4050 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4051 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4052 err_code |= ERR_ALERT | ERR_FATAL;
4053 goto out;
4054 }
4055 }
4056 else if (strcmp(ptr_arg, "rstring") == 0) {
4057 if (!*(args[cur_arg + 1])) {
4058 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4059 file, linenum, args[0], args[1], ptr_arg);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004064 free(curproxy->expect_str);
4065 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
4066 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01004067 curproxy->expect_regex = calloc(1, sizeof(regex_t));
4068 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4069 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4070 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4071 err_code |= ERR_ALERT | ERR_FATAL;
4072 goto out;
4073 }
4074 }
4075 else {
4076 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4077 file, linenum, args[0], args[1], ptr_arg);
4078 err_code |= ERR_ALERT | ERR_FATAL;
4079 goto out;
4080 }
4081 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004082 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004083 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 +02004084 err_code |= ERR_ALERT | ERR_FATAL;
4085 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004086 }
4087 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004088 else if (!strcmp(args[0], "tcp-check")) {
4089 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4090 err_code |= ERR_WARN;
4091
4092 if (strcmp(args[1], "send") == 0) {
4093 if (! *(args[2]) ) {
4094 /* SEND string expected */
4095 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4096 file, linenum, args[0], args[1], args[2]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 } else {
4100 struct tcpcheck_rule *tcpcheck;
4101
4102 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4103
4104 tcpcheck->action = TCPCHK_ACT_SEND;
4105 tcpcheck->string_len = strlen(args[2]);
4106 tcpcheck->string = strdup(args[2]);
4107 tcpcheck->expect_regex = NULL;
4108
4109 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4110 }
4111 }
4112 else if (strcmp(args[1], "send-binary") == 0) {
4113 if (! *(args[2]) ) {
4114 /* SEND binary string expected */
4115 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4116 file, linenum, args[0], args[1], args[2]);
4117 err_code |= ERR_ALERT | ERR_FATAL;
4118 goto out;
4119 } else {
4120 struct tcpcheck_rule *tcpcheck;
4121 char *err = NULL;
4122
4123 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4124
4125 tcpcheck->action = TCPCHK_ACT_SEND;
4126 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4127 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4128 file, linenum, args[0], args[1], args[2], err);
4129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
4131 }
4132 tcpcheck->expect_regex = NULL;
4133
4134 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4135 }
4136 }
4137 else if (strcmp(args[1], "expect") == 0) {
4138 const char *ptr_arg;
4139 int cur_arg;
4140 int inverse = 0;
4141
4142 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4143 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
4146 }
4147
4148 cur_arg = 2;
4149 /* consider exclamation marks, sole or at the beginning of a word */
4150 while (*(ptr_arg = args[cur_arg])) {
4151 while (*ptr_arg == '!') {
4152 inverse = !inverse;
4153 ptr_arg++;
4154 }
4155 if (*ptr_arg)
4156 break;
4157 cur_arg++;
4158 }
4159 /* now ptr_arg points to the beginning of a word past any possible
4160 * exclamation mark, and cur_arg is the argument which holds this word.
4161 */
4162 if (strcmp(ptr_arg, "binary") == 0) {
4163 if (!*(args[cur_arg + 1])) {
4164 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4165 file, linenum, args[0], args[1], ptr_arg);
4166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
4169 struct tcpcheck_rule *tcpcheck;
4170 char *err = NULL;
4171
4172 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4173
4174 tcpcheck->action = TCPCHK_ACT_EXPECT;
4175 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4176 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4177 file, linenum, args[0], args[1], args[2], err);
4178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
4180 }
4181 tcpcheck->expect_regex = NULL;
4182 tcpcheck->inverse = inverse;
4183
4184 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4185 }
4186 else if (strcmp(ptr_arg, "string") == 0) {
4187 if (!*(args[cur_arg + 1])) {
4188 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4189 file, linenum, args[0], args[1], ptr_arg);
4190 err_code |= ERR_ALERT | ERR_FATAL;
4191 goto out;
4192 }
4193 struct tcpcheck_rule *tcpcheck;
4194
4195 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4196
4197 tcpcheck->action = TCPCHK_ACT_EXPECT;
4198 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4199 tcpcheck->string = strdup(args[cur_arg + 1]);
4200 tcpcheck->expect_regex = NULL;
4201 tcpcheck->inverse = inverse;
4202
4203 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4204 }
4205 else if (strcmp(ptr_arg, "rstring") == 0) {
4206 if (!*(args[cur_arg + 1])) {
4207 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4208 file, linenum, args[0], args[1], ptr_arg);
4209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
4211 }
4212 struct tcpcheck_rule *tcpcheck;
4213
4214 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4215
4216 tcpcheck->action = TCPCHK_ACT_EXPECT;
4217 tcpcheck->string_len = 0;
4218 tcpcheck->string = NULL;
4219 tcpcheck->expect_regex = calloc(1, sizeof(regex_t));
4220 if (regcomp(tcpcheck->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
4221 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
4222 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
4223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
4225 }
4226 tcpcheck->inverse = inverse;
4227
4228 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4229 }
4230 else {
4231 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4232 file, linenum, args[0], args[1], ptr_arg);
4233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
4235 }
4236 }
4237 else {
4238 Alert("parsing [%s:%d] : '%s' only supports 'send' or 'expect'.\n", file, linenum, args[0]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
4241 }
4242 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004243 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004244 if (curproxy == &defproxy) {
4245 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004248 }
4249
Willy Tarreaub80c2302007-11-30 20:51:32 +01004250 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004252
4253 if (strcmp(args[1], "fail") == 0) {
4254 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004255 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004256 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4257 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004258 err_code |= ERR_ALERT | ERR_FATAL;
4259 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004260 }
4261
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004262 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4263 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4264 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004267 }
4268 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4269 }
4270 else {
4271 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004272 err_code |= ERR_ALERT | ERR_FATAL;
4273 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004274 }
4275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004276#ifdef TPROXY
4277 else if (!strcmp(args[0], "transparent")) {
4278 /* enable transparent proxy connections */
4279 curproxy->options |= PR_O_TRANSP;
4280 }
4281#endif
4282 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004283 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004284 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004285
Willy Tarreaubaaee002006-06-26 02:48:02 +02004286 if (*(args[1]) == 0) {
4287 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 }
4291 curproxy->maxconn = atol(args[1]);
4292 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004293 else if (!strcmp(args[0], "backlog")) { /* backlog */
4294 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004295 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004296
4297 if (*(args[1]) == 0) {
4298 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004299 err_code |= ERR_ALERT | ERR_FATAL;
4300 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004301 }
4302 curproxy->backlog = atol(args[1]);
4303 }
Willy Tarreau86034312006-12-29 00:10:33 +01004304 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004305 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004306 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004307
Willy Tarreau86034312006-12-29 00:10:33 +01004308 if (*(args[1]) == 0) {
4309 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004310 err_code |= ERR_ALERT | ERR_FATAL;
4311 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004312 }
4313 curproxy->fullconn = atol(args[1]);
4314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004315 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4316 if (*(args[1]) == 0) {
4317 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004318 err_code |= ERR_ALERT | ERR_FATAL;
4319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004320 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004321 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4322 if (err) {
4323 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4324 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004325 err_code |= ERR_ALERT | ERR_FATAL;
4326 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004327 }
4328 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 }
4330 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004331 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004332 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004333 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004334
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 if (curproxy == &defproxy) {
4336 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004337 err_code |= ERR_ALERT | ERR_FATAL;
4338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004340 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004341 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004342
Willy Tarreau902636f2013-03-10 19:44:48 +01004343 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004344 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004345 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004346 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004347 goto out;
4348 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004349
4350 proto = protocol_by_family(sk->ss_family);
4351 if (!proto || !proto->connect) {
4352 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4353 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
4356 }
4357
4358 if (port1 != port2) {
4359 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4360 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004363 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004364
4365 if (!port1) {
4366 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4367 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004371
Willy Tarreaud5191e72010-02-09 20:50:45 +01004372 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004373 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004374 }
4375 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004376 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004377 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004378
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004379 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4380 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004381 err_code |= ERR_ALERT | ERR_FATAL;
4382 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004385 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004386 /**
4387 * The syntax for hash-type config element is
4388 * hash-type {map-based|consistent} [[<algo>] avalanche]
4389 *
4390 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4391 */
4392 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004393
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004394 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4395 err_code |= ERR_WARN;
4396
4397 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004398 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4399 }
4400 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004401 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4402 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004403 else if (strcmp(args[1], "avalanche") == 0) {
4404 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]);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004407 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004408 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004409 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
4412 }
Bhaskar98634f02013-10-29 23:30:51 -04004413
4414 /* set the hash function to use */
4415 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004416 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004417 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004418
4419 /* if consistent with no argument, then avalanche modifier is also applied */
4420 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4421 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004422 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004423 /* set the hash function */
4424 if (!strcmp(args[2], "sdbm")) {
4425 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4426 }
4427 else if (!strcmp(args[2], "djb2")) {
4428 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004429 } else if (!strcmp(args[2], "wt6")) {
4430 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004431 }
4432 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004433 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 -05004434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
4436 }
4437
4438 /* set the hash modifier */
4439 if (!strcmp(args[3], "avalanche")) {
4440 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4441 }
4442 else if (*args[3]) {
4443 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
4446 }
Bhaskar98634f02013-10-29 23:30:51 -04004447 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004448 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004449 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004451 short realport = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004452 int do_agent = 0, do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02004453
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004454 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004455 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_FATAL;
4457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004458 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004459 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004460 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004461
4462 if (!*args[2]) {
4463 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
4464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004465 err_code |= ERR_ALERT | ERR_FATAL;
4466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004468
4469 err = invalid_char(args[1]);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004470 if (err && !defsrv) {
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004471 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4472 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004473 err_code |= ERR_ALERT | ERR_FATAL;
4474 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004475 }
4476
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004477 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004478 struct sockaddr_storage *sk;
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004479 int port1, port2;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004480 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004481
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004482 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4483 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4484 err_code |= ERR_ALERT | ERR_ABORT;
4485 goto out;
4486 }
4487
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004488 /* the servers are linked backwards first */
4489 newsrv->next = curproxy->srv;
4490 curproxy->srv = newsrv;
4491 newsrv->proxy = curproxy;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02004492 newsrv->conf.file = strdup(file);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004493 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494
Willy Tarreau3fdb3662012-11-12 00:42:33 +01004495 newsrv->obj_type = OBJ_TYPE_SERVER;
Simon Hormanaf514952011-06-21 14:34:57 +09004496 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004497 LIST_INIT(&newsrv->pendconns);
4498 do_check = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004499 do_agent = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004500 newsrv->state = SRV_RUNNING; /* early server setup */
4501 newsrv->last_change = now.tv_sec;
4502 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004504 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004505 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004506 * - IP: => port=+0, relative
4507 * - IP:N => port=N, absolute
4508 * - IP:+N => port=+N, relative
4509 * - IP:-N => port=-N, relative
4510 */
Willy Tarreau902636f2013-03-10 19:44:48 +01004511 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004512 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004513 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004514 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004515 goto out;
4516 }
Willy Tarreau4217a7d2013-03-06 20:04:27 +01004517
4518 proto = protocol_by_family(sk->ss_family);
4519 if (!proto || !proto->connect) {
4520 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4521 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004522 err_code |= ERR_ALERT | ERR_FATAL;
4523 goto out;
4524 }
Willy Tarreaudbfa4452013-02-20 19:06:35 +01004525
4526 if (!port1 || !port2) {
4527 /* no port specified, +offset, -offset */
4528 newsrv->state |= SRV_MAPPORTS;
4529 }
4530 else if (port1 != port2) {
4531 /* port range */
4532 Alert("parsing [%s:%d] : '%s %s' : port ranges are not allowed in '%s'\n",
4533 file, linenum, args[0], args[1], args[2]);
4534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
4536 }
4537 else {
4538 /* used by checks */
4539 realport = port1;
4540 }
4541
Willy Tarreaud5191e72010-02-09 20:50:45 +01004542 newsrv->addr = *sk;
Simon Horman66183002013-02-23 10:16:43 +09004543 newsrv->proto = newsrv->check_common.proto = protocol_by_family(newsrv->addr.ss_family);
4544 newsrv->xprt = newsrv->check_common.xprt = &raw_sock;
Willy Tarreau26d8c592012-05-07 18:12:14 +02004545
Willy Tarreau173e7fb2012-09-24 22:47:39 +02004546 if (!newsrv->proto) {
Willy Tarreau26d8c592012-05-07 18:12:14 +02004547 Alert("parsing [%s:%d] : Unknown protocol family %d '%s'\n",
4548 file, linenum, newsrv->addr.ss_family, args[2]);
4549 err_code |= ERR_ALERT | ERR_FATAL;
4550 goto out;
4551 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004552
Simon Hormand60d6912013-11-25 10:46:36 +09004553 newsrv->check.use_ssl = curproxy->defsrv.check.use_ssl;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004554 newsrv->check.port = curproxy->defsrv.check.port;
Simon Horman66183002013-02-23 10:16:43 +09004555 newsrv->check.inter = curproxy->defsrv.check.inter;
4556 newsrv->check.fastinter = curproxy->defsrv.check.fastinter;
4557 newsrv->check.downinter = curproxy->defsrv.check.downinter;
Simon Hormand60d6912013-11-25 10:46:36 +09004558 newsrv->agent.use_ssl = curproxy->defsrv.agent.use_ssl;
4559 newsrv->agent.port = curproxy->defsrv.agent.port;
4560 newsrv->agent.inter = curproxy->defsrv.agent.inter;
4561 newsrv->agent.fastinter = curproxy->defsrv.agent.fastinter;
4562 newsrv->agent.downinter = curproxy->defsrv.agent.downinter;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004563 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4564 newsrv->minconn = curproxy->defsrv.minconn;
4565 newsrv->maxconn = curproxy->defsrv.maxconn;
4566 newsrv->slowstart = curproxy->defsrv.slowstart;
4567 newsrv->onerror = curproxy->defsrv.onerror;
4568 newsrv->consecutive_errors_limit
4569 = curproxy->defsrv.consecutive_errors_limit;
Emeric Brun01f8e2f2012-05-18 16:02:00 +02004570#ifdef OPENSSL
4571 newsrv->use_ssl = curproxy->defsrv.use_ssl;
4572#endif
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004573 newsrv->uweight = newsrv->iweight
4574 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004575
Simon Horman69d29f92013-02-23 15:14:19 +09004576 newsrv->check.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004577 newsrv->check.rise = curproxy->defsrv.check.rise;
4578 newsrv->check.fall = curproxy->defsrv.check.fall;
4579 newsrv->check.health = newsrv->check.rise; /* up, but will fall down at first failure */
Simon Horman69d29f92013-02-23 15:14:19 +09004580 newsrv->check.server = newsrv;
4581
Simon Hormand60d6912013-11-25 10:46:36 +09004582 newsrv->agent.status = HCHK_STATUS_INI;
Simon Horman58c32972013-11-25 10:46:38 +09004583 newsrv->agent.rise = curproxy->defsrv.agent.rise;
4584 newsrv->agent.fall = curproxy->defsrv.agent.fall;
4585 newsrv->agent.health = newsrv->agent.rise; /* up, but will fall down at first failure */
Simon Hormand60d6912013-11-25 10:46:36 +09004586 newsrv->agent.server = newsrv;
4587
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004588 cur_arg = 3;
4589 } else {
4590 newsrv = &curproxy->defsrv;
4591 cur_arg = 1;
4592 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004593
Willy Tarreaubaaee002006-06-26 02:48:02 +02004594 while (*args[cur_arg]) {
Simon Hormand60d6912013-11-25 10:46:36 +09004595 if (!strcmp(args[cur_arg], "agent-check")) {
4596 global.maxsock++;
4597 do_agent = 1;
4598 cur_arg += 1;
4599 } else if (!strcmp(args[cur_arg], "agent-inter")) {
4600 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4601 if (err) {
4602 Alert("parsing [%s:%d] : unexpected character '%c' in 'agent-inter' argument of server %s.\n",
4603 file, linenum, *err, newsrv->id);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
4607 if (val <= 0) {
4608 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4609 file, linenum, val, args[cur_arg], newsrv->id);
4610 err_code |= ERR_ALERT | ERR_FATAL;
4611 goto out;
4612 }
4613 newsrv->agent.inter = val;
4614 cur_arg += 2;
4615 }
4616 else if (!strcmp(args[cur_arg], "agent-port")) {
4617 global.maxsock++;
4618 newsrv->agent.port = atol(args[cur_arg + 1]);
4619 cur_arg += 2;
4620 }
4621 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004622 newsrv->cookie = strdup(args[cur_arg + 1]);
4623 newsrv->cklen = strlen(args[cur_arg + 1]);
4624 cur_arg += 2;
4625 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004626 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004627 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4628 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4629 cur_arg += 2;
4630 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004632 if (!*args[cur_arg + 1]) {
4633 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4634 file, linenum, args[cur_arg]);
4635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
4637 }
4638
Simon Horman58c32972013-11-25 10:46:38 +09004639 newsrv->check.rise = atol(args[cur_arg + 1]);
4640 if (newsrv->check.rise <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004641 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4642 file, linenum, args[cur_arg]);
4643 err_code |= ERR_ALERT | ERR_FATAL;
4644 goto out;
4645 }
4646
Simon Horman125d0992013-02-24 17:23:38 +09004647 if (newsrv->check.health)
Simon Horman58c32972013-11-25 10:46:38 +09004648 newsrv->check.health = newsrv->check.rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004649 cur_arg += 2;
4650 }
4651 else if (!strcmp(args[cur_arg], "fall")) {
Simon Horman58c32972013-11-25 10:46:38 +09004652 newsrv->check.fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004653
4654 if (!*args[cur_arg + 1]) {
4655 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4656 file, linenum, args[cur_arg]);
4657 err_code |= ERR_ALERT | ERR_FATAL;
4658 goto out;
4659 }
4660
Simon Horman58c32972013-11-25 10:46:38 +09004661 if (newsrv->check.fall <= 0) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004662 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4663 file, linenum, args[cur_arg]);
4664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
4666 }
4667
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 cur_arg += 2;
4669 }
4670 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004671 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4672 if (err) {
4673 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4674 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004675 err_code |= ERR_ALERT | ERR_FATAL;
4676 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004677 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004678 if (val <= 0) {
4679 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4680 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004683 }
Simon Horman66183002013-02-23 10:16:43 +09004684 newsrv->check.inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685 cur_arg += 2;
4686 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004687 else if (!strcmp(args[cur_arg], "fastinter")) {
4688 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4689 if (err) {
4690 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4691 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004692 err_code |= ERR_ALERT | ERR_FATAL;
4693 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004694 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004695 if (val <= 0) {
4696 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4697 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004698 err_code |= ERR_ALERT | ERR_FATAL;
4699 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004700 }
Simon Horman66183002013-02-23 10:16:43 +09004701 newsrv->check.fastinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004702 cur_arg += 2;
4703 }
4704 else if (!strcmp(args[cur_arg], "downinter")) {
4705 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4706 if (err) {
4707 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4708 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004709 err_code |= ERR_ALERT | ERR_FATAL;
4710 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004711 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004712 if (val <= 0) {
4713 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4714 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004717 }
Simon Horman66183002013-02-23 10:16:43 +09004718 newsrv->check.downinter = val;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004719 cur_arg += 2;
4720 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004721 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004722 struct sockaddr_storage *sk;
4723 int port1, port2;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004724 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004725
Willy Tarreau902636f2013-03-10 19:44:48 +01004726 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004727 if (!sk) {
Willy Tarreau1a20b142013-03-06 18:05:34 +01004728 Alert("parsing [%s:%d] : '%s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004729 file, linenum, args[cur_arg], errmsg);
Willy Tarreau1a20b142013-03-06 18:05:34 +01004730 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau1a20b142013-03-06 18:05:34 +01004731 goto out;
4732 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004733
4734 proto = protocol_by_family(sk->ss_family);
4735 if (!proto || !proto->connect) {
4736 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004737 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004738 err_code |= ERR_ALERT | ERR_FATAL;
4739 goto out;
4740 }
Willy Tarreau1a20b142013-03-06 18:05:34 +01004741
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004742 if (port1 != port2) {
4743 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4744 file, linenum, args[cur_arg], args[cur_arg + 1]);
4745 err_code |= ERR_ALERT | ERR_FATAL;
4746 goto out;
4747 }
4748
Simon Horman66183002013-02-23 10:16:43 +09004749 newsrv->check_common.addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004750 cur_arg += 2;
4751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 else if (!strcmp(args[cur_arg], "port")) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02004753 newsrv->check.port = atol(args[cur_arg + 1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004754 cur_arg += 2;
4755 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004756 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 newsrv->state |= SRV_BACKUP;
4758 cur_arg ++;
4759 }
Simon Hormanfa461682011-06-25 09:39:49 +09004760 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4761 newsrv->state |= SRV_NON_STICK;
4762 cur_arg ++;
4763 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004764 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4765 newsrv->state |= SRV_SEND_PROXY;
4766 cur_arg ++;
4767 }
Willy Tarreau6c16adc2012-10-05 00:04:16 +02004768 else if (!defsrv && !strcmp(args[cur_arg], "check-send-proxy")) {
4769 newsrv->check.send_proxy = 1;
4770 cur_arg ++;
4771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 else if (!strcmp(args[cur_arg], "weight")) {
4773 int w;
4774 w = atol(args[cur_arg + 1]);
Godbacha34bdc02013-07-22 07:44:53 +08004775 if (w < 0 || w > SRV_UWGHT_MAX) {
4776 Alert("parsing [%s:%d] : weight of server %s is not within 0 and %d (%d).\n",
4777 file, linenum, newsrv->id, SRV_UWGHT_MAX, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004778 err_code |= ERR_ALERT | ERR_FATAL;
4779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004780 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004781 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 cur_arg += 2;
4783 }
4784 else if (!strcmp(args[cur_arg], "minconn")) {
4785 newsrv->minconn = atol(args[cur_arg + 1]);
4786 cur_arg += 2;
4787 }
4788 else if (!strcmp(args[cur_arg], "maxconn")) {
4789 newsrv->maxconn = atol(args[cur_arg + 1]);
4790 cur_arg += 2;
4791 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004792 else if (!strcmp(args[cur_arg], "maxqueue")) {
4793 newsrv->maxqueue = atol(args[cur_arg + 1]);
4794 cur_arg += 2;
4795 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004796 else if (!strcmp(args[cur_arg], "slowstart")) {
4797 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004798 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004799 if (err) {
4800 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4801 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004802 err_code |= ERR_ALERT | ERR_FATAL;
4803 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004804 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004805 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004806 cur_arg += 2;
4807 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004808 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004809
4810 if (!*args[cur_arg + 1]) {
4811 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4812 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004815 }
4816
4817 newsrv->trackit = strdup(args[cur_arg + 1]);
4818
4819 cur_arg += 2;
4820 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004821 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 global.maxsock++;
4823 do_check = 1;
4824 cur_arg += 1;
4825 }
Willy Tarreau96839092010-03-29 10:02:24 +02004826 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4827 newsrv->state |= SRV_MAINTAIN;
4828 newsrv->state &= ~SRV_RUNNING;
Willy Tarreau33a08db2013-12-11 21:03:31 +01004829 newsrv->check.state |= CHK_ST_PAUSED;
Simon Horman125d0992013-02-24 17:23:38 +09004830 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09004831 newsrv->agent.health = 0;
Willy Tarreau96839092010-03-29 10:02:24 +02004832 cur_arg += 1;
Emeric Brunc0ff4922012-09-28 19:37:02 +02004833 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004834 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004835 if (!strcmp(args[cur_arg + 1], "none"))
4836 newsrv->observe = HANA_OBS_NONE;
4837 else if (!strcmp(args[cur_arg + 1], "layer4"))
4838 newsrv->observe = HANA_OBS_LAYER4;
4839 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4840 if (curproxy->mode != PR_MODE_HTTP) {
4841 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4842 file, linenum, args[cur_arg + 1]);
4843 err_code |= ERR_ALERT;
4844 }
4845 newsrv->observe = HANA_OBS_LAYER7;
4846 }
4847 else {
4848 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004849 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004850 file, linenum, args[cur_arg], args[cur_arg + 1]);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
4854
4855 cur_arg += 2;
4856 }
4857 else if (!strcmp(args[cur_arg], "on-error")) {
4858 if (!strcmp(args[cur_arg + 1], "fastinter"))
4859 newsrv->onerror = HANA_ONERR_FASTINTER;
4860 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4861 newsrv->onerror = HANA_ONERR_FAILCHK;
4862 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4863 newsrv->onerror = HANA_ONERR_SUDDTH;
4864 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4865 newsrv->onerror = HANA_ONERR_MARKDWN;
4866 else {
4867 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004868 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004869 file, linenum, args[cur_arg], args[cur_arg + 1]);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
4873
4874 cur_arg += 2;
4875 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004876 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4877 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4878 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4879 else {
4880 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4881 file, linenum, args[cur_arg], args[cur_arg + 1]);
4882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
4884 }
4885
4886 cur_arg += 2;
4887 }
Justin Karnegeseb2c24a2012-05-24 15:28:52 -07004888 else if (!strcmp(args[cur_arg], "on-marked-up")) {
4889 if (!strcmp(args[cur_arg + 1], "shutdown-backup-sessions"))
4890 newsrv->onmarkedup = HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS;
4891 else {
4892 Alert("parsing [%s:%d]: '%s' expects 'shutdown-backup-sessions' but got '%s'\n",
4893 file, linenum, args[cur_arg], args[cur_arg + 1]);
4894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
4896 }
4897
4898 cur_arg += 2;
4899 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004900 else if (!strcmp(args[cur_arg], "error-limit")) {
4901 if (!*args[cur_arg + 1]) {
4902 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4903 file, linenum, args[cur_arg]);
4904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
4906 }
4907
4908 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4909
4910 if (newsrv->consecutive_errors_limit <= 0) {
4911 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4912 file, linenum, args[cur_arg]);
4913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
4915 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004916 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004917 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004918 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004919 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004920 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004921 struct protocol *proto;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004922
Willy Tarreaubaaee002006-06-26 02:48:02 +02004923 if (!*args[cur_arg + 1]) {
Willy Tarreaueb37faa2012-12-08 23:21:19 +01004924 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optionally '%s' <addr>, and '%s' <name> as argument.\n",
4925 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004926 err_code |= ERR_ALERT | ERR_FATAL;
4927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004928 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004929
Willy Tarreauef9a3602012-12-08 22:29:20 +01004930 newsrv->conn_src.opts |= CO_SRC_BIND;
Willy Tarreau902636f2013-03-10 19:44:48 +01004931 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004932 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004933 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004934 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004935 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004936 goto out;
4937 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004938
4939 proto = protocol_by_family(sk->ss_family);
4940 if (!proto || !proto->connect) {
4941 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4942 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
4945 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004946
Willy Tarreauef9a3602012-12-08 22:29:20 +01004947 newsrv->conn_src.source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004948
4949 if (port_low != port_high) {
4950 int i;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004951
4952 if (!port_low || !port_high) {
4953 Alert("parsing [%s:%d] : %s does not support port offsets (found '%s').\n",
4954 file, linenum, args[cur_arg], args[cur_arg + 1]);
4955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
4957 }
4958
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004959 if (port_low <= 0 || port_low > 65535 ||
4960 port_high <= 0 || port_high > 65535 ||
4961 port_low > port_high) {
4962 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4963 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004966 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01004967 newsrv->conn_src.sport_range = port_range_alloc_range(port_high - port_low + 1);
4968 for (i = 0; i < newsrv->conn_src.sport_range->size; i++)
4969 newsrv->conn_src.sport_range->ports[i] = port_low + i;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004970 }
4971
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004973 while (*(args[cur_arg])) {
4974 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02004975#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
4976#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01004977 if (!is_addr(&newsrv->conn_src.source_addr)) {
Willy Tarreauc76721d2009-02-04 20:20:58 +01004978 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4979 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004982 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004983#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004984 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004985 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004986 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004989 }
4990 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004991 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4992 newsrv->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004993 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01004994 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4995 newsrv->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004996 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4997 char *name, *end;
4998
4999 name = args[cur_arg+1] + 7;
5000 while (isspace(*name))
5001 name++;
5002
5003 end = name;
5004 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5005 end++;
5006
Willy Tarreauef9a3602012-12-08 22:29:20 +01005007 newsrv->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5008 newsrv->conn_src.opts |= CO_SRC_TPROXY_DYN;
5009 newsrv->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5010 newsrv->conn_src.bind_hdr_len = end - name;
5011 memcpy(newsrv->conn_src.bind_hdr_name, name, end - name);
5012 newsrv->conn_src.bind_hdr_name[end-name] = '\0';
5013 newsrv->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005014
5015 /* now look for an occurrence number */
5016 while (isspace(*end))
5017 end++;
5018 if (*end == ',') {
5019 end++;
5020 name = end;
5021 if (*end == '-')
5022 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005023 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005024 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005025 newsrv->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005026 }
5027
Willy Tarreauef9a3602012-12-08 22:29:20 +01005028 if (newsrv->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005029 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5030 " occurrences values smaller than %d.\n",
5031 file, linenum, MAX_HDR_HISTORY);
5032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
5034 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01005035 } else {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005036 struct sockaddr_storage *sk;
5037 int port1, port2;
5038
Willy Tarreau902636f2013-03-10 19:44:48 +01005039 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005040 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005041 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005042 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005043 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005044 goto out;
5045 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005046
5047 proto = protocol_by_family(sk->ss_family);
5048 if (!proto || !proto->connect) {
5049 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5050 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
5053 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005054
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005055 if (port1 != port2) {
5056 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5057 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005058 err_code |= ERR_ALERT | ERR_FATAL;
5059 goto out;
5060 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005061 newsrv->conn_src.tproxy_addr = *sk;
5062 newsrv->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005063 }
5064 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005065#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauc76721d2009-02-04 20:20:58 +01005066 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005067#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005068 cur_arg += 2;
5069 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005070#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005071 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005072 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005075#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) */
Willy Tarreauc76721d2009-02-04 20:20:58 +01005076 } /* "usesrc" */
5077
5078 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5079#ifdef SO_BINDTODEVICE
5080 if (!*args[cur_arg + 1]) {
5081 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5082 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01005085 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005086 free(newsrv->conn_src.iface_name);
5087 newsrv->conn_src.iface_name = strdup(args[cur_arg + 1]);
5088 newsrv->conn_src.iface_len = strlen(newsrv->conn_src.iface_name);
Willy Tarreauc76721d2009-02-04 20:20:58 +01005089 global.last_checks |= LSTCHK_NETADM;
5090#else
5091 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5092 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005093 err_code |= ERR_ALERT | ERR_FATAL;
5094 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01005095#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01005096 cur_arg += 2;
5097 continue;
5098 }
5099 /* this keyword in not an option of "source" */
5100 break;
5101 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005102 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005103 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005104 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5105 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005109 else {
Willy Tarreaud0d60592012-10-10 08:57:40 +02005110 static int srv_dumped;
5111 struct srv_kw *kw;
5112 char *err;
5113
5114 kw = srv_find_kw(args[cur_arg]);
5115 if (kw) {
5116 char *err = NULL;
5117 int code;
5118
5119 if (!kw->parse) {
5120 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
5121 file, linenum, args[0], args[1], args[cur_arg]);
5122 cur_arg += 1 + kw->skip ;
5123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
5125 }
5126
5127 if (defsrv && !kw->default_ok) {
5128 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not accepted in default-server sections.\n",
5129 file, linenum, args[0], args[1], args[cur_arg]);
5130 cur_arg += 1 + kw->skip ;
5131 err_code |= ERR_ALERT;
5132 continue;
5133 }
5134
5135 code = kw->parse(args, &cur_arg, curproxy, newsrv, &err);
5136 err_code |= code;
5137
5138 if (code) {
5139 if (err && *err) {
5140 indent_msg(&err, 2);
5141 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
5142 }
5143 else
5144 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
5145 file, linenum, args[0], args[1], args[cur_arg]);
5146 if (code & ERR_FATAL) {
5147 free(err);
5148 cur_arg += 1 + kw->skip;
5149 goto out;
5150 }
5151 }
5152 free(err);
5153 cur_arg += 1 + kw->skip;
5154 continue;
5155 }
5156
5157 err = NULL;
5158 if (!srv_dumped) {
5159 srv_dump_kws(&err);
5160 indent_msg(&err, 4);
5161 srv_dumped = 1;
5162 }
5163
5164 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
5165 file, linenum, args[0], args[1], args[cur_arg],
5166 err ? " Registered keywords :" : "", err ? err : "");
5167 free(err);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005168
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005171 }
5172 }
5173
Simon Horman8c3d0be2013-11-25 10:46:40 +09005174 /* Set initial drain state using now-configured weight */
5175 set_server_drain_state(newsrv);
5176
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 if (do_check) {
Simon Horman69d29f92013-02-23 15:14:19 +09005178 int ret;
5179
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005180 if (newsrv->trackit) {
5181 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
5182 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005185 }
5186
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005187 /* If neither a port nor an addr was specified and no check transport
5188 * layer is forced, then the transport layer used by the checks is the
5189 * same as for the production traffic. Otherwise we use raw_sock by
5190 * default, unless one is specified.
5191 */
Simon Horman66183002013-02-23 10:16:43 +09005192 if (!newsrv->check.port && !is_addr(&newsrv->check_common.addr)) {
Willy Tarreau71516332012-10-10 23:01:14 +02005193#ifdef USE_OPENSSL
Willy Tarreauf4288ee2012-09-28 18:13:10 +02005194 newsrv->check.use_ssl |= newsrv->use_ssl;
Willy Tarreau71516332012-10-10 23:01:14 +02005195#endif
Willy Tarreau6c16adc2012-10-05 00:04:16 +02005196 newsrv->check.send_proxy |= (newsrv->state & SRV_SEND_PROXY);
5197 }
Simon Horman66183002013-02-23 10:16:43 +09005198 /* try to get the port from check_core.addr if check.port not set */
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005199 if (!newsrv->check.port)
Simon Horman66183002013-02-23 10:16:43 +09005200 newsrv->check.port = get_host_port(&newsrv->check_common.addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02005201
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005202 if (!newsrv->check.port)
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005203 newsrv->check.port = realport; /* by default */
Willy Tarreaudbfa4452013-02-20 19:06:35 +01005204
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005205 if (!newsrv->check.port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01005206 /* not yet valid, because no port was set on
5207 * the server either. We'll check if we have
5208 * a known port on the first listener.
5209 */
Willy Tarreau4348fad2012-09-20 16:48:07 +02005210 struct listener *l;
5211
5212 list_for_each_entry(l, &curproxy->conf.listeners, by_fe) {
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005213 newsrv->check.port = get_host_port(&l->addr);
5214 if (newsrv->check.port)
Willy Tarreau4348fad2012-09-20 16:48:07 +02005215 break;
5216 }
Willy Tarreauef00b502007-01-07 02:40:09 +01005217 }
Willy Tarreau5b3a2022012-09-28 15:01:02 +02005218 if (!newsrv->check.port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005219 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
5220 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
Willy Tarreau1ae1b7b2012-09-28 15:28:30 +02005224
Willy Tarreau2f075e92013-12-03 11:11:34 +01005225 /* note: check type will be set during the config review phase */
5226 ret = init_check(&newsrv->check, 0, file, linenum);
Simon Horman69d29f92013-02-23 15:14:19 +09005227 if (ret) {
5228 err_code |= ret;
Willy Tarreauda92e2f2012-07-06 09:40:59 +02005229 goto out;
5230 }
5231
Willy Tarreau2e10f5a2013-12-11 20:11:55 +01005232 newsrv->check.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 }
5234
Simon Hormand60d6912013-11-25 10:46:36 +09005235 if (do_agent) {
5236 int ret;
5237
5238 if (!newsrv->agent.port) {
5239 Alert("parsing [%s:%d] : server %s does not have agent port. Agent check has been disabled.\n",
5240 file, linenum, newsrv->id);
5241 err_code |= ERR_ALERT | ERR_FATAL;
5242 goto out;
5243 }
5244
5245 if (!newsrv->agent.inter)
5246 newsrv->agent.inter = newsrv->check.inter;
5247
5248 ret = init_check(&newsrv->agent, PR_O2_LB_AGENT_CHK, file, linenum);
5249 if (ret) {
5250 err_code |= ret;
5251 goto out;
5252 }
5253
Willy Tarreau33434322013-12-11 21:15:19 +01005254 newsrv->agent.state |= CHK_ST_CONFIGURED | CHK_ST_ENABLED | CHK_ST_AGENT;
Simon Hormand60d6912013-11-25 10:46:36 +09005255 }
5256
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005257 if (!defsrv) {
5258 if (newsrv->state & SRV_BACKUP)
5259 curproxy->srv_bck++;
5260 else
5261 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01005262
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005263 newsrv->prev_state = newsrv->state;
5264 }
William Lallemanda73203e2012-03-12 12:48:57 +01005265 }
5266
5267 else if (strcmp(args[0], "unique-id-format") == 0) {
5268 if (!*(args[1])) {
5269 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
5272 }
William Lallemand3203ff42012-11-11 17:30:56 +01005273 if (*(args[2])) {
5274 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
5277 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005278 free(curproxy->conf.uniqueid_format_string);
5279 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005280
Willy Tarreau62a61232013-04-12 18:13:46 +02005281 free(curproxy->conf.uif_file);
5282 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5283 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005284 }
William Lallemanda73203e2012-03-12 12:48:57 +01005285
5286 else if (strcmp(args[0], "unique-id-header") == 0) {
5287 if (!*(args[1])) {
5288 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
5291 }
5292 free(curproxy->header_unique_id);
5293 curproxy->header_unique_id = strdup(args[1]);
5294 }
5295
William Lallemand723b73a2012-02-08 16:37:49 +01005296 else if (strcmp(args[0], "log-format") == 0) {
5297 if (!*(args[1])) {
5298 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5299 err_code |= ERR_ALERT | ERR_FATAL;
5300 goto out;
5301 }
William Lallemand3203ff42012-11-11 17:30:56 +01005302 if (*(args[2])) {
5303 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
5306 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005307
Willy Tarreau62a61232013-04-12 18:13:46 +02005308 if (curproxy->conf.logformat_string != default_http_log_format &&
5309 curproxy->conf.logformat_string != default_tcp_log_format &&
5310 curproxy->conf.logformat_string != clf_http_log_format)
5311 free(curproxy->conf.logformat_string);
5312 curproxy->conf.logformat_string = strdup(args[1]);
5313
5314 free(curproxy->conf.lfs_file);
5315 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5316 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005317
5318 /* get a chance to improve log-format error reporting by
5319 * reporting the correct line-number when possible.
5320 */
5321 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5322 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5323 file, linenum, curproxy->id);
5324 err_code |= ERR_WARN;
5325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005326 }
William Lallemand723b73a2012-02-08 16:37:49 +01005327
William Lallemand0f99e342011-10-12 17:50:54 +02005328 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5329 /* delete previous herited or defined syslog servers */
5330 struct logsrv *back;
5331
5332 if (*(args[1]) != 0) {
5333 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
5336 }
5337
William Lallemand723b73a2012-02-08 16:37:49 +01005338 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5339 LIST_DEL(&tmplogsrv->list);
5340 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005341 }
5342 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005343 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005344 struct logsrv *logsrv;
5345
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005347 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005348 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005349 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005350 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005351 LIST_INIT(&node->list);
5352 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5353 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005354 }
5355 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005356 struct sockaddr_storage *sk;
5357 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02005358
5359 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360
William Lallemand0f99e342011-10-12 17:50:54 +02005361 logsrv->facility = get_log_facility(args[2]);
5362 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
5366
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 }
5368
William Lallemand0f99e342011-10-12 17:50:54 +02005369 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005371 logsrv->level = get_log_level(args[3]);
5372 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005373 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005374 err_code |= ERR_ALERT | ERR_FATAL;
5375 goto out;
5376
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
5378 }
5379
William Lallemand0f99e342011-10-12 17:50:54 +02005380 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005381 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02005382 logsrv->minlvl = get_log_level(args[4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005383 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005384 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005385 err_code |= ERR_ALERT | ERR_FATAL;
5386 goto out;
5387
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005388 }
5389 }
5390
Willy Tarreau902636f2013-03-10 19:44:48 +01005391 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005392 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005393 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005394 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005395 goto out;
5396 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005397
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005398 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005399
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005400 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005401 if (port1 != port2) {
5402 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5403 file, linenum, args[0], args[1]);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005408 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005409 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 }
William Lallemand0f99e342011-10-12 17:50:54 +02005411
5412 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005413 }
5414 else {
5415 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5416 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
5420 }
5421 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005422 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005423 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005424 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005425 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005426
Willy Tarreau977b8e42006-12-29 14:19:17 +01005427 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005428 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005429
Willy Tarreaubaaee002006-06-26 02:48:02 +02005430 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005431 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5432 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005436
5437 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005438 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5439 free(curproxy->conn_src.iface_name);
5440 curproxy->conn_src.iface_name = NULL;
5441 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005442
Willy Tarreau902636f2013-03-10 19:44:48 +01005443 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005444 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005445 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005446 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005447 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005448 goto out;
5449 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005450
5451 proto = protocol_by_family(sk->ss_family);
5452 if (!proto || !proto->connect) {
5453 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005454 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005455 err_code |= ERR_ALERT | ERR_FATAL;
5456 goto out;
5457 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005458
5459 if (port1 != port2) {
5460 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5461 file, linenum, args[0], args[1]);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
5465
Willy Tarreauef9a3602012-12-08 22:29:20 +01005466 curproxy->conn_src.source_addr = *sk;
5467 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005468
5469 cur_arg = 2;
5470 while (*(args[cur_arg])) {
5471 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005472#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5473#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01005474 if (!is_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005475 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5476 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005479 }
5480#endif
5481 if (!*args[cur_arg + 1]) {
5482 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5483 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005484 err_code |= ERR_ALERT | ERR_FATAL;
5485 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005486 }
5487
5488 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005489 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5490 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005491 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005492 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5493 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005494 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5495 char *name, *end;
5496
5497 name = args[cur_arg+1] + 7;
5498 while (isspace(*name))
5499 name++;
5500
5501 end = name;
5502 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5503 end++;
5504
Willy Tarreauef9a3602012-12-08 22:29:20 +01005505 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5506 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5507 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5508 curproxy->conn_src.bind_hdr_len = end - name;
5509 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5510 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5511 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005512
5513 /* now look for an occurrence number */
5514 while (isspace(*end))
5515 end++;
5516 if (*end == ',') {
5517 end++;
5518 name = end;
5519 if (*end == '-')
5520 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005521 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005522 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005523 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005524 }
5525
Willy Tarreauef9a3602012-12-08 22:29:20 +01005526 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005527 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5528 " occurrences values smaller than %d.\n",
5529 file, linenum, MAX_HDR_HISTORY);
5530 err_code |= ERR_ALERT | ERR_FATAL;
5531 goto out;
5532 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005533 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005534 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005535
Willy Tarreau902636f2013-03-10 19:44:48 +01005536 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005537 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005538 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005539 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005540 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005541 goto out;
5542 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005543
5544 proto = protocol_by_family(sk->ss_family);
5545 if (!proto || !proto->connect) {
5546 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5547 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005548 err_code |= ERR_ALERT | ERR_FATAL;
5549 goto out;
5550 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005551
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005552 if (port1 != port2) {
5553 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5554 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005555 err_code |= ERR_ALERT | ERR_FATAL;
5556 goto out;
5557 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005558 curproxy->conn_src.tproxy_addr = *sk;
5559 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005560 }
5561 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005562#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005563 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005564#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005565#else /* no TPROXY support */
5566 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005567 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005570#endif
5571 cur_arg += 2;
5572 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005573 }
5574
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005575 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5576#ifdef SO_BINDTODEVICE
5577 if (!*args[cur_arg + 1]) {
5578 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5579 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005580 err_code |= ERR_ALERT | ERR_FATAL;
5581 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005582 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005583 free(curproxy->conn_src.iface_name);
5584 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5585 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005586 global.last_checks |= LSTCHK_NETADM;
5587#else
5588 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5589 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005590 err_code |= ERR_ALERT | ERR_FATAL;
5591 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005592#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005593 cur_arg += 2;
5594 continue;
5595 }
5596 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005597 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005598 err_code |= ERR_ALERT | ERR_FATAL;
5599 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005600 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005601 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005602 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5603 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5604 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005608 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005609 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5611 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005612 err_code |= ERR_ALERT | ERR_FATAL;
5613 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005614 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005615
5616 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005617 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005618 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005619 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005620 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005621 }
5622 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005623 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005624 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005625 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005626 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005627 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005628 }
5629 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005630 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005631 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005632 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005633 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005635 }
5636 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005637 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005638 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005639 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005640 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005642 }
5643 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005644 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005645 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005646 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005647 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005650 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005651 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005652 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005653 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005654 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005655 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005656 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005657 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005658 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005659 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005660 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005661 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005662 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005663 }
5664 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005665 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005666 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005667 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005668 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005669 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01005670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005671 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005672 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5674 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005675 err_code |= ERR_ALERT | ERR_FATAL;
5676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005677 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005678
5679 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005680 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005681 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005682 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 }
5685 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005686 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005687 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005688 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005689 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
5692 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005693 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005694 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005695 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005696 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005698 }
5699 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005700 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005701 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005702 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005703 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005705 }
5706 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005707 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005708 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005709 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005710 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005712 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005713 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005714 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005715 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005716 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005717 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005718 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005721 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005722
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723 if (curproxy == &defproxy) {
5724 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005728 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005729 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730
Willy Tarreaubaaee002006-06-26 02:48:02 +02005731 if (*(args[1]) == 0) {
5732 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005733 err_code |= ERR_ALERT | ERR_FATAL;
5734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005735 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005736
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005737 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005738 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5739 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5740 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
5743 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005744 err_code |= warnif_cond_conflicts(cond,
5745 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5746 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005747 }
5748 else if (*args[2]) {
5749 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5750 file, linenum, args[0], args[2]);
5751 err_code |= ERR_ALERT | ERR_FATAL;
5752 goto out;
5753 }
5754
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005755 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005756 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005757 wl->s = strdup(args[1]);
5758 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005759 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 }
5761 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005762 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005763 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5764 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005765 err_code |= ERR_ALERT | ERR_FATAL;
5766 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005767 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005768
Willy Tarreauade5ec42010-01-28 19:33:49 +01005769 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005770 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005771 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005772 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005774 }
5775 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005776 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005777 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005778 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005779 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005781 }
5782 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005783 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005784 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005785 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005786 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005788 }
5789 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005790 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5792 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005795 }
5796
Willy Tarreauade5ec42010-01-28 19:33:49 +01005797 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005798 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005799 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005800 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
5803 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005804 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005805 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005806 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005807 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 }
5810 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005811 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005812 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005813 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005814 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 }
5817 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005818 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005819
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 if (curproxy == &defproxy) {
5821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005822 err_code |= ERR_ALERT | ERR_FATAL;
5823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005824 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005825 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005826 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827
Willy Tarreaubaaee002006-06-26 02:48:02 +02005828 if (*(args[1]) == 0) {
5829 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005832 }
5833
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005834 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005835 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5836 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5837 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005838 err_code |= ERR_ALERT | ERR_FATAL;
5839 goto out;
5840 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005841 err_code |= warnif_cond_conflicts(cond,
5842 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5843 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005844 }
5845 else if (*args[2]) {
5846 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5847 file, linenum, args[0], args[2]);
5848 err_code |= ERR_ALERT | ERR_FATAL;
5849 goto out;
5850 }
5851
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005852 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005853 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005854 wl->s = strdup(args[1]);
5855 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005856 }
5857 else if (!strcmp(args[0], "errorloc") ||
5858 !strcmp(args[0], "errorloc302") ||
5859 !strcmp(args[0], "errorloc303")) { /* error location */
5860 int errnum, errlen;
5861 char *err;
5862
Willy Tarreau977b8e42006-12-29 14:19:17 +01005863 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005864 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005865
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005867 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005870 }
5871
5872 errnum = atol(args[1]);
5873 if (!strcmp(args[0], "errorloc303")) {
5874 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5875 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5876 } else {
5877 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5878 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5879 }
5880
Willy Tarreau0f772532006-12-23 20:51:41 +01005881 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5882 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005883 chunk_destroy(&curproxy->errmsg[rc]);
5884 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005885 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005887 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005888
5889 if (rc >= HTTP_ERR_SIZE) {
5890 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5891 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 free(err);
5893 }
5894 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005895 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5896 int errnum, errlen, fd;
5897 char *err;
5898 struct stat stat;
5899
5900 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005901 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005902
5903 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005904 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005905 err_code |= ERR_ALERT | ERR_FATAL;
5906 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005907 }
5908
5909 fd = open(args[2], O_RDONLY);
5910 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5911 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5912 file, linenum, args[2], args[1]);
5913 if (fd >= 0)
5914 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005915 err_code |= ERR_ALERT | ERR_FATAL;
5916 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005917 }
5918
Willy Tarreau27a674e2009-08-17 07:23:33 +02005919 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005920 errlen = stat.st_size;
5921 } else {
5922 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005923 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005924 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005925 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005926 }
5927
5928 err = malloc(errlen); /* malloc() must succeed during parsing */
5929 errnum = read(fd, err, errlen);
5930 if (errnum != errlen) {
5931 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5932 file, linenum, args[2], args[1]);
5933 close(fd);
5934 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005935 err_code |= ERR_ALERT | ERR_FATAL;
5936 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005937 }
5938 close(fd);
5939
5940 errnum = atol(args[1]);
5941 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5942 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005943 chunk_destroy(&curproxy->errmsg[rc]);
5944 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005945 break;
5946 }
5947 }
5948
5949 if (rc >= HTTP_ERR_SIZE) {
5950 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5951 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005952 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005953 free(err);
5954 }
5955 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005956 else if (!strcmp(args[0], "compression")) {
5957 struct comp *comp;
5958 if (curproxy->comp == NULL) {
5959 comp = calloc(1, sizeof(struct comp));
5960 curproxy->comp = comp;
5961 } else {
5962 comp = curproxy->comp;
5963 }
5964
5965 if (!strcmp(args[1], "algo")) {
5966 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005967 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005968
William Lallemand82fe75c2012-10-23 10:25:10 +02005969 cur_arg = 2;
5970 if (!*args[cur_arg]) {
5971 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5972 file, linenum, args[0]);
5973 err_code |= ERR_ALERT | ERR_FATAL;
5974 goto out;
5975 }
5976 while (*(args[cur_arg])) {
5977 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5978 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5979 file, linenum, args[0], args[cur_arg]);
5980 err_code |= ERR_ALERT | ERR_FATAL;
5981 goto out;
5982 }
William Lallemand552df672012-11-07 13:21:47 +01005983 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5984 curproxy->comp->algos->end(&ctx);
5985 } else {
5986 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5987 file, linenum, args[0], args[cur_arg]);
5988 err_code |= ERR_ALERT | ERR_FATAL;
5989 goto out;
5990 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005991 cur_arg ++;
5992 continue;
5993 }
5994 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005995 else if (!strcmp(args[1], "offload")) {
5996 comp->offload = 1;
5997 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005998 else if (!strcmp(args[1], "type")) {
5999 int cur_arg;
6000 cur_arg = 2;
6001 if (!*args[cur_arg]) {
6002 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6003 file, linenum, args[0]);
6004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
6006 }
6007 while (*(args[cur_arg])) {
6008 comp_append_type(comp, args[cur_arg]);
6009 cur_arg ++;
6010 continue;
6011 }
6012 }
6013 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006014 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006015 file, linenum, args[0]);
6016 err_code |= ERR_ALERT | ERR_FATAL;
6017 goto out;
6018 }
6019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006021 struct cfg_kw_list *kwl;
6022 int index;
6023
6024 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6025 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6026 if (kwl->kw[index].section != CFG_LISTEN)
6027 continue;
6028 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6029 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006030 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006031 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006032 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006033 err_code |= ERR_ALERT | ERR_FATAL;
6034 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006035 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006036 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006037 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006038 err_code |= ERR_WARN;
6039 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006040 }
Willy Tarreau93893792009-07-23 13:19:11 +02006041 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006042 }
6043 }
6044 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006045
Willy Tarreau6daf3432008-01-22 16:44:08 +01006046 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006047 err_code |= ERR_ALERT | ERR_FATAL;
6048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006049 }
Willy Tarreau93893792009-07-23 13:19:11 +02006050 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006051 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006052 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053}
6054
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006055int
6056cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6057{
6058
6059 int err_code = 0;
6060 const char *err;
6061
6062 if (!strcmp(args[0], "userlist")) { /* new userlist */
6063 struct userlist *newul;
6064
6065 if (!*args[1]) {
6066 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6067 file, linenum, args[0]);
6068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
6071
6072 err = invalid_char(args[1]);
6073 if (err) {
6074 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6075 file, linenum, *err, args[0], args[1]);
6076 err_code |= ERR_ALERT | ERR_FATAL;
6077 goto out;
6078 }
6079
6080 for (newul = userlist; newul; newul = newul->next)
6081 if (!strcmp(newul->name, args[1])) {
6082 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6083 file, linenum, args[1]);
6084 err_code |= ERR_WARN;
6085 goto out;
6086 }
6087
6088 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6089 if (!newul) {
6090 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6091 err_code |= ERR_ALERT | ERR_ABORT;
6092 goto out;
6093 }
6094
6095 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
6096 newul->name = strdup(args[1]);
6097
6098 if (!newul->groupusers | !newul->name) {
6099 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6100 err_code |= ERR_ALERT | ERR_ABORT;
6101 goto out;
6102 }
6103
6104 newul->next = userlist;
6105 userlist = newul;
6106
6107 } else if (!strcmp(args[0], "group")) { /* new group */
6108 int cur_arg, i;
6109 const char *err;
6110
6111 if (!*args[1]) {
6112 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6113 file, linenum, args[0]);
6114 err_code |= ERR_ALERT | ERR_FATAL;
6115 goto out;
6116 }
6117
6118 err = invalid_char(args[1]);
6119 if (err) {
6120 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6121 file, linenum, *err, args[0], args[1]);
6122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
6124 }
6125
6126 for(i = 0; i < userlist->grpcnt; i++)
6127 if (!strcmp(userlist->groups[i], args[1])) {
6128 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6129 file, linenum, args[1], userlist->name);
6130 err_code |= ERR_ALERT;
6131 goto out;
6132 }
6133
6134 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
6135 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
6136 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
6137 err_code |= ERR_ALERT | ERR_FATAL;
6138 goto out;
6139 }
6140
6141 cur_arg = 2;
6142
6143 while (*args[cur_arg]) {
6144 if (!strcmp(args[cur_arg], "users")) {
6145 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
6146 cur_arg += 2;
6147 continue;
6148 } else {
6149 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6150 file, linenum, args[0]);
6151 err_code |= ERR_ALERT | ERR_FATAL;
6152 goto out;
6153 }
6154 }
6155
6156 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
6157 } else if (!strcmp(args[0], "user")) { /* new user */
6158 struct auth_users *newuser;
6159 int cur_arg;
6160
6161 if (!*args[1]) {
6162 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6163 file, linenum, args[0]);
6164 err_code |= ERR_ALERT | ERR_FATAL;
6165 goto out;
6166 }
6167
6168 for (newuser = userlist->users; newuser; newuser = newuser->next)
6169 if (!strcmp(newuser->user, args[1])) {
6170 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6171 file, linenum, args[1], userlist->name);
6172 err_code |= ERR_ALERT;
6173 goto out;
6174 }
6175
6176 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6177 if (!newuser) {
6178 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6179 err_code |= ERR_ALERT | ERR_ABORT;
6180 goto out;
6181 }
6182
6183 newuser->user = strdup(args[1]);
6184
6185 newuser->next = userlist->users;
6186 userlist->users = newuser;
6187
6188 cur_arg = 2;
6189
6190 while (*args[cur_arg]) {
6191 if (!strcmp(args[cur_arg], "password")) {
6192#ifndef CONFIG_HAP_CRYPT
6193 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6194 file, linenum);
6195 err_code |= ERR_ALERT;
6196#endif
6197 newuser->pass = strdup(args[cur_arg + 1]);
6198 cur_arg += 2;
6199 continue;
6200 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6201 newuser->pass = strdup(args[cur_arg + 1]);
6202 newuser->flags |= AU_O_INSECURE;
6203 cur_arg += 2;
6204 continue;
6205 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006206 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006207 cur_arg += 2;
6208 continue;
6209 } else {
6210 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6211 file, linenum, args[0]);
6212 err_code |= ERR_ALERT | ERR_FATAL;
6213 goto out;
6214 }
6215 }
6216 } else {
6217 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6218 err_code |= ERR_ALERT | ERR_FATAL;
6219 }
6220
6221out:
6222 return err_code;
6223}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006224
6225/*
6226 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006227 * Returns the error code, 0 if OK, or any combination of :
6228 * - ERR_ABORT: must abort ASAP
6229 * - ERR_FATAL: we can continue parsing but not start the service
6230 * - ERR_WARN: a warning has been emitted
6231 * - ERR_ALERT: an alert has been emitted
6232 * Only the two first ones can stop processing, the two others are just
6233 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006234 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006235int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006236{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006237 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006238 FILE *f;
6239 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006240 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02006241 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006242
Willy Tarreaubaaee002006-06-26 02:48:02 +02006243 if ((f=fopen(file,"r")) == NULL)
6244 return -1;
6245
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006246 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006247 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006248 char *end;
6249 char *args[MAX_LINE_ARGS + 1];
6250 char *line = thisline;
6251
Willy Tarreaubaaee002006-06-26 02:48:02 +02006252 linenum++;
6253
6254 end = line + strlen(line);
6255
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006256 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6257 /* Check if we reached the limit and the last char is not \n.
6258 * Watch out for the last line without the terminating '\n'!
6259 */
6260 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006261 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006262 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006263 }
6264
Willy Tarreaubaaee002006-06-26 02:48:02 +02006265 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006266 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 line++;
6268
6269 arg = 0;
6270 args[arg] = line;
6271
6272 while (*line && arg < MAX_LINE_ARGS) {
6273 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6274 * C equivalent value. Other combinations left unchanged (eg: \1).
6275 */
6276 if (*line == '\\') {
6277 int skip = 0;
6278 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6279 *line = line[1];
6280 skip = 1;
6281 }
6282 else if (line[1] == 'r') {
6283 *line = '\r';
6284 skip = 1;
6285 }
6286 else if (line[1] == 'n') {
6287 *line = '\n';
6288 skip = 1;
6289 }
6290 else if (line[1] == 't') {
6291 *line = '\t';
6292 skip = 1;
6293 }
6294 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006295 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006296 unsigned char hex1, hex2;
6297 hex1 = toupper(line[2]) - '0';
6298 hex2 = toupper(line[3]) - '0';
6299 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6300 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6301 *line = (hex1<<4) + hex2;
6302 skip = 3;
6303 }
6304 else {
6305 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006306 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006307 }
6308 }
6309 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006310 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006311 end -= skip;
6312 }
6313 line++;
6314 }
6315 else if (*line == '#' || *line == '\n' || *line == '\r') {
6316 /* end of string, end of loop */
6317 *line = 0;
6318 break;
6319 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006320 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006321 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006322 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006323 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 line++;
6325 args[++arg] = line;
6326 }
6327 else {
6328 line++;
6329 }
6330 }
6331
6332 /* empty line */
6333 if (!**args)
6334 continue;
6335
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006336 if (*line) {
6337 /* we had to stop due to too many args.
6338 * Let's terminate the string, print the offending part then cut the
6339 * last arg.
6340 */
6341 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6342 line++;
6343 *line = '\0';
6344
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006345 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006346 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006347 err_code |= ERR_ALERT | ERR_FATAL;
6348 args[arg] = line;
6349 }
6350
Willy Tarreau540abe42007-05-02 20:50:16 +02006351 /* zero out remaining args and ensure that at least one entry
6352 * is zeroed out.
6353 */
6354 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355 args[arg] = line;
6356 }
6357
Willy Tarreau3842f002009-06-14 11:39:52 +02006358 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006359 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006360 char *tmp;
6361
Willy Tarreau3842f002009-06-14 11:39:52 +02006362 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006363 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006364 for (arg=0; *args[arg+1]; arg++)
6365 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006366 *tmp = '\0'; // fix the next arg to \0
6367 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006368 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006369 else if (!strcmp(args[0], "default")) {
6370 kwm = KWM_DEF;
6371 for (arg=0; *args[arg+1]; arg++)
6372 args[arg] = args[arg+1]; // shift args after inversion
6373 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006374
William Lallemand0f99e342011-10-12 17:50:54 +02006375 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6376 strcmp(args[0], "log") != 0) {
6377 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006378 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006379 }
6380
Willy Tarreau977b8e42006-12-29 14:19:17 +01006381 if (!strcmp(args[0], "listen") ||
6382 !strcmp(args[0], "frontend") ||
6383 !strcmp(args[0], "backend") ||
6384 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01006385 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006386 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006387 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006388 cursection = strdup(args[0]);
6389 }
6390 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02006392 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006393 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02006394 }
6395 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006396 confsect = CFG_USERLIST;
6397 free(cursection);
6398 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006399 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006400 else if (!strcmp(args[0], "peers")) {
6401 confsect = CFG_PEERS;
6402 free(cursection);
6403 cursection = strdup(args[0]);
6404 }
6405
Willy Tarreaubaaee002006-06-26 02:48:02 +02006406 /* else it's a section keyword */
6407
6408 switch (confsect) {
6409 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02006410 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006411 break;
6412 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02006413 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006414 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006415 case CFG_USERLIST:
6416 err_code |= cfg_parse_users(file, linenum, args, kwm);
6417 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02006418 case CFG_PEERS:
6419 err_code |= cfg_parse_peers(file, linenum, args, kwm);
6420 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006422 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006423 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006424 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006425
6426 if (err_code & ERR_ABORT)
6427 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02006429 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01006430 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006432 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006433}
6434
Willy Tarreaubb925012009-07-23 13:36:36 +02006435/*
6436 * Returns the error code, 0 if OK, or any combination of :
6437 * - ERR_ABORT: must abort ASAP
6438 * - ERR_FATAL: we can continue parsing but not start the service
6439 * - ERR_WARN: a warning has been emitted
6440 * - ERR_ALERT: an alert has been emitted
6441 * Only the two first ones can stop processing, the two others are just
6442 * indicators.
6443 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006444int check_config_validity()
6445{
6446 int cfgerr = 0;
6447 struct proxy *curproxy = NULL;
6448 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006449 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006450 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006451 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006452 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006454 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 /*
6456 * Now, check for the integrity of all that we have collected.
6457 */
6458
6459 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006460 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461
Willy Tarreau193b8c62012-11-22 00:17:38 +01006462 if (!global.tune.max_http_hdr)
6463 global.tune.max_http_hdr = MAX_HTTP_HDR;
6464
6465 if (!global.tune.cookie_len)
6466 global.tune.cookie_len = CAPTURE_LEN;
6467
6468 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6469
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006470 /* first, we will invert the proxy list order */
6471 curproxy = NULL;
6472 while (proxy) {
6473 struct proxy *next;
6474
6475 next = proxy->next;
6476 proxy->next = curproxy;
6477 curproxy = proxy;
6478 if (!next)
6479 break;
6480 proxy = next;
6481 }
6482
Willy Tarreaubaaee002006-06-26 02:48:02 +02006483 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006484 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006485 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006486 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006487 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006488 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006489 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006490 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006491
Willy Tarreau050536d2012-10-04 08:47:34 +02006492 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006493 /* proxy ID not set, use automatic numbering with first
6494 * spare entry starting with next_pxid.
6495 */
6496 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6497 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6498 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006499 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006500 next_pxid++;
6501
Willy Tarreau55ea7572007-06-17 19:56:27 +02006502
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006504 /* ensure we don't keep listeners uselessly bound */
6505 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506 curproxy = curproxy->next;
6507 continue;
6508 }
6509
Willy Tarreau16a21472012-11-19 12:39:59 +01006510 /* number of processes this proxy is bound to */
6511 nbproc = curproxy->bind_proc ? popcount(curproxy->bind_proc) : global.nbproc;
6512
Willy Tarreauff01a212009-03-15 13:46:16 +01006513 switch (curproxy->mode) {
6514 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006515 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006516 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006517 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6518 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006519 cfgerr++;
6520 }
6521
6522 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006523 Warning("config : servers will be ignored for %s '%s'.\n",
6524 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006525 break;
6526
6527 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006528 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006529 break;
6530
6531 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006532 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006533 break;
6534 }
6535
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006536 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006537 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006538 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006539 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6540 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006541 cfgerr++;
6542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006543#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006544 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006545 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6546 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006547 cfgerr++;
6548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006549#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006550 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006551 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6552 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006553 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006554 }
6555 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006556 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006557 /* If no LB algo is set in a backend, and we're not in
6558 * transparent mode, dispatch mode nor proxy mode, we
6559 * want to use balance roundrobin by default.
6560 */
6561 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6562 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006563 }
6564 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006565
Willy Tarreau1620ec32011-08-06 17:05:02 +02006566 if (curproxy->options & PR_O_DISPATCH)
6567 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6568 else if (curproxy->options & PR_O_HTTP_PROXY)
6569 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6570 else if (curproxy->options & PR_O_TRANSP)
6571 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006572
Willy Tarreau1620ec32011-08-06 17:05:02 +02006573 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6574 if (curproxy->options & PR_O_DISABLE404) {
6575 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6576 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6577 err_code |= ERR_WARN;
6578 curproxy->options &= ~PR_O_DISABLE404;
6579 }
6580 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6581 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6582 "send-state", proxy_type_str(curproxy), curproxy->id);
6583 err_code |= ERR_WARN;
6584 curproxy->options &= ~PR_O2_CHK_SNDST;
6585 }
Willy Tarreauef781042010-01-27 11:53:01 +01006586 }
6587
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006588 /* if a default backend was specified, let's find it */
6589 if (curproxy->defbe.name) {
6590 struct proxy *target;
6591
Alex Williams96532db2009-11-01 21:27:13 -05006592 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006593 if (!target) {
6594 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6595 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006596 cfgerr++;
6597 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006598 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6599 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006600 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006601 } else {
6602 free(curproxy->defbe.name);
6603 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006604 /* we force the backend to be present on at least all of
6605 * the frontend's processes.
6606 */
6607 target->bind_proc = curproxy->bind_proc ?
6608 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01006609
6610 /* Emit a warning if this proxy also has some servers */
6611 if (curproxy->srv) {
6612 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6613 curproxy->id);
6614 err_code |= ERR_WARN;
6615 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006616 }
6617 }
6618
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006619 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006620 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6621 /* map jump target for ACT_SETBE in req_rep chain */
6622 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006623 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006624 struct proxy *target;
6625
Willy Tarreaua496b602006-12-17 23:15:24 +01006626 if (exp->action != ACT_SETBE)
6627 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006628
Alex Williams96532db2009-11-01 21:27:13 -05006629 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006630 if (!target) {
6631 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6632 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006633 cfgerr++;
6634 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006635 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6636 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006637 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006638 } else {
6639 free((void *)exp->replace);
6640 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006641 /* we force the backend to be present on at least all of
6642 * the frontend's processes.
6643 */
6644 target->bind_proc = curproxy->bind_proc ?
6645 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01006646 }
6647 }
6648 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006649
6650 /* find the target proxy for 'use_backend' rules */
6651 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006652 struct proxy *target;
6653
Alex Williams96532db2009-11-01 21:27:13 -05006654 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006655
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006656 if (!target) {
6657 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6658 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006659 cfgerr++;
6660 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006661 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6662 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006663 cfgerr++;
6664 } else {
6665 free((void *)rule->be.name);
6666 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01006667 /* we force the backend to be present on at least all of
6668 * the frontend's processes.
6669 */
6670 target->bind_proc = curproxy->bind_proc ?
6671 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006672 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006673 }
6674
6675 /* find the target proxy for 'use_backend' rules */
6676 list_for_each_entry(srule, &curproxy->server_rules, list) {
6677 struct server *target = findserver(curproxy, srule->srv.name);
6678
6679 if (!target) {
6680 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6681 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6682 cfgerr++;
6683 continue;
6684 }
6685 free((void *)srule->srv.name);
6686 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006687 }
6688
Emeric Brunb982a3d2010-01-04 15:45:53 +01006689 /* find the target table for 'stick' rules */
6690 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6691 struct proxy *target;
6692
Emeric Brun1d33b292010-01-04 15:47:17 +01006693 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6694 if (mrule->flags & STK_IS_STORE)
6695 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6696
Emeric Brunb982a3d2010-01-04 15:45:53 +01006697 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006698 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006699 else
6700 target = curproxy;
6701
6702 if (!target) {
6703 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6704 curproxy->id, mrule->table.name);
6705 cfgerr++;
6706 }
6707 else if (target->table.size == 0) {
6708 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6709 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6710 cfgerr++;
6711 }
Willy Tarreau12785782012-04-27 21:37:17 +02006712 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6713 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006714 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6715 cfgerr++;
6716 }
6717 else {
6718 free((void *)mrule->table.name);
6719 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006720 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006721 }
6722 }
6723
6724 /* find the target table for 'store response' rules */
6725 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6726 struct proxy *target;
6727
Emeric Brun1d33b292010-01-04 15:47:17 +01006728 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6729
Emeric Brunb982a3d2010-01-04 15:45:53 +01006730 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006731 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006732 else
6733 target = curproxy;
6734
6735 if (!target) {
6736 Alert("Proxy '%s': unable to find store table '%s'.\n",
6737 curproxy->id, mrule->table.name);
6738 cfgerr++;
6739 }
6740 else if (target->table.size == 0) {
6741 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6742 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6743 cfgerr++;
6744 }
Willy Tarreau12785782012-04-27 21:37:17 +02006745 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6746 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006747 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6748 cfgerr++;
6749 }
6750 else {
6751 free((void *)mrule->table.name);
6752 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006753 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006754 }
6755 }
6756
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006757 /* find the target table for 'tcp-request' layer 4 rules */
6758 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6759 struct proxy *target;
6760
Willy Tarreaub4c84932013-07-23 19:15:30 +02006761 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006762 continue;
6763
6764 if (trule->act_prm.trk_ctr.table.n)
6765 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6766 else
6767 target = curproxy;
6768
6769 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006770 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6771 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006772 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006773 cfgerr++;
6774 }
6775 else if (target->table.size == 0) {
6776 Alert("Proxy '%s': table '%s' used but not configured.\n",
6777 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6778 cfgerr++;
6779 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006780 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6781 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6782 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 +01006783 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006784 cfgerr++;
6785 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006786 else {
6787 free(trule->act_prm.trk_ctr.table.n);
6788 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006789 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006790 * to pass a list of counters to track and allocate them right here using
6791 * stktable_alloc_data_type().
6792 */
6793 }
6794 }
6795
Willy Tarreaud1f96522010-08-03 19:34:32 +02006796 /* find the target table for 'tcp-request' layer 6 rules */
6797 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6798 struct proxy *target;
6799
Willy Tarreaub4c84932013-07-23 19:15:30 +02006800 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006801 continue;
6802
6803 if (trule->act_prm.trk_ctr.table.n)
6804 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6805 else
6806 target = curproxy;
6807
6808 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006809 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6810 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006811 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006812 cfgerr++;
6813 }
6814 else if (target->table.size == 0) {
6815 Alert("Proxy '%s': table '%s' used but not configured.\n",
6816 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6817 cfgerr++;
6818 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006819 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6820 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6821 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 +01006822 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006823 cfgerr++;
6824 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006825 else {
6826 free(trule->act_prm.trk_ctr.table.n);
6827 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006828 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006829 * to pass a list of counters to track and allocate them right here using
6830 * stktable_alloc_data_type().
6831 */
6832 }
6833 }
6834
Emeric Brun32da3c42010-09-23 18:39:19 +02006835 if (curproxy->table.peers.name) {
6836 struct peers *curpeers = peers;
6837
6838 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6839 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6840 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006841 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006842 break;
6843 }
6844 }
6845
6846 if (!curpeers) {
6847 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6848 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006849 free((void *)curproxy->table.peers.name);
6850 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006851 cfgerr++;
6852 }
6853 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006854 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6855 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006856 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006857 cfgerr++;
6858 }
6859 }
6860
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006861 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006862 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006863 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6864 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6865 "proxy", curproxy->id);
6866 cfgerr++;
6867 goto out_uri_auth_compat;
6868 }
6869
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006870 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006871 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006872 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006873 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006874
Willy Tarreau95fa4692010-02-01 13:05:50 +01006875 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6876 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006877
6878 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006879 uri_auth_compat_req[i++] = "realm";
6880 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6881 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006882
Willy Tarreau95fa4692010-02-01 13:05:50 +01006883 uri_auth_compat_req[i++] = "unless";
6884 uri_auth_compat_req[i++] = "{";
6885 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6886 uri_auth_compat_req[i++] = "}";
6887 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006888
Willy Tarreauff011f22011-01-06 17:51:27 +01006889 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6890 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006891 cfgerr++;
6892 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006893 }
6894
Willy Tarreauff011f22011-01-06 17:51:27 +01006895 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006896
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006897 if (curproxy->uri_auth->auth_realm) {
6898 free(curproxy->uri_auth->auth_realm);
6899 curproxy->uri_auth->auth_realm = NULL;
6900 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006901
6902 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006903 }
6904out_uri_auth_compat:
6905
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006906 /* compile the log format */
6907 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006908 if (curproxy->conf.logformat_string != default_http_log_format &&
6909 curproxy->conf.logformat_string != default_tcp_log_format &&
6910 curproxy->conf.logformat_string != clf_http_log_format)
6911 free(curproxy->conf.logformat_string);
6912 curproxy->conf.logformat_string = NULL;
6913 free(curproxy->conf.lfs_file);
6914 curproxy->conf.lfs_file = NULL;
6915 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006916 }
6917
Willy Tarreau62a61232013-04-12 18:13:46 +02006918 if (curproxy->conf.logformat_string) {
6919 curproxy->conf.args.ctx = ARGC_LOG;
6920 curproxy->conf.args.file = curproxy->conf.lfs_file;
6921 curproxy->conf.args.line = curproxy->conf.lfs_line;
6922 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006923 SMP_VAL_FE_LOG_END);
Willy Tarreau62a61232013-04-12 18:13:46 +02006924 curproxy->conf.args.file = NULL;
6925 curproxy->conf.args.line = 0;
6926 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006927
Willy Tarreau62a61232013-04-12 18:13:46 +02006928 if (curproxy->conf.uniqueid_format_string) {
6929 curproxy->conf.args.ctx = ARGC_UIF;
6930 curproxy->conf.args.file = curproxy->conf.uif_file;
6931 curproxy->conf.args.line = curproxy->conf.uif_line;
6932 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, 0,
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006933 (proxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR);
Willy Tarreau62a61232013-04-12 18:13:46 +02006934 curproxy->conf.args.file = NULL;
6935 curproxy->conf.args.line = 0;
6936 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006937
6938 /* only now we can check if some args remain unresolved */
6939 cfgerr += smp_resolve_args(curproxy);
6940 if (!cfgerr)
6941 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006942
Willy Tarreau2738a142006-07-08 17:28:09 +02006943 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006944 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006945 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006946 (!curproxy->timeout.connect ||
6947 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006948 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006949 " | While not properly invalid, you will certainly encounter various problems\n"
6950 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006951 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006952 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006953 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006954 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006955
Willy Tarreau1fa31262007-12-03 00:36:16 +01006956 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6957 * We must still support older configurations, so let's find out whether those
6958 * parameters have been set or must be copied from contimeouts.
6959 */
6960 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006961 if (!curproxy->timeout.tarpit ||
6962 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006963 /* tarpit timeout not set. We search in the following order:
6964 * default.tarpit, curr.connect, default.connect.
6965 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006966 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006967 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006968 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006969 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006970 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006971 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006972 }
6973 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006974 (!curproxy->timeout.queue ||
6975 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006976 /* queue timeout not set. We search in the following order:
6977 * default.queue, curr.connect, default.connect.
6978 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006979 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006980 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006981 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006982 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006983 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006984 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006985 }
6986 }
6987
Willy Tarreau1620ec32011-08-06 17:05:02 +02006988 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006989 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6990 curproxy->check_req = (char *)malloc(curproxy->check_len);
6991 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006992 }
6993
Willy Tarreau193b8c62012-11-22 00:17:38 +01006994 /* ensure that cookie capture length is not too large */
6995 if (curproxy->capture_len >= global.tune.cookie_len) {
6996 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6997 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6998 err_code |= ERR_WARN;
6999 curproxy->capture_len = global.tune.cookie_len - 1;
7000 }
7001
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007002 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007003 if (curproxy->nb_req_cap) {
7004 if (curproxy->mode == PR_MODE_HTTP) {
7005 curproxy->req_cap_pool = create_pool("ptrcap",
7006 curproxy->nb_req_cap * sizeof(char *),
7007 MEM_F_SHARED);
7008 } else {
7009 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
7010 proxy_type_str(curproxy), curproxy->id);
7011 err_code |= ERR_WARN;
7012 curproxy->to_log &= ~LW_REQHDR;
7013 curproxy->nb_req_cap = 0;
7014 }
7015 }
7016
7017 if (curproxy->nb_rsp_cap) {
7018 if (curproxy->mode == PR_MODE_HTTP) {
7019 curproxy->rsp_cap_pool = create_pool("ptrcap",
7020 curproxy->nb_rsp_cap * sizeof(char *),
7021 MEM_F_SHARED);
7022 } else {
7023 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
7024 proxy_type_str(curproxy), curproxy->id);
7025 err_code |= ERR_WARN;
7026 curproxy->to_log &= ~LW_REQHDR;
7027 curproxy->nb_rsp_cap = 0;
7028 }
7029 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007030
Willy Tarreaubaaee002006-06-26 02:48:02 +02007031 /* first, we will invert the servers list order */
7032 newsrv = NULL;
7033 while (curproxy->srv) {
7034 struct server *next;
7035
7036 next = curproxy->srv->next;
7037 curproxy->srv->next = newsrv;
7038 newsrv = curproxy->srv;
7039 if (!next)
7040 break;
7041 curproxy->srv = next;
7042 }
7043
Willy Tarreau17edc812014-01-03 12:14:34 +01007044 /* Check that no server name conflicts. This causes trouble in the stats.
7045 * We only emit a warning for the first conflict affecting each server,
7046 * in order to avoid combinatory explosion if all servers have the same
7047 * name. We do that only for servers which do not have an explicit ID,
7048 * because these IDs were made also for distinguishing them and we don't
7049 * want to annoy people who correctly manage them.
7050 */
7051 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7052 struct server *other_srv;
7053
7054 if (newsrv->puid)
7055 continue;
7056
7057 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7058 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7059 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7060 newsrv->conf.file, newsrv->conf.line,
7061 proxy_type_str(curproxy), curproxy->id,
7062 newsrv->id, other_srv->conf.line);
7063 break;
7064 }
7065 }
7066 }
7067
Willy Tarreaudd701652010-05-25 23:03:02 +02007068 /* assign automatic UIDs to servers which don't have one yet */
7069 next_id = 1;
7070 newsrv = curproxy->srv;
7071 while (newsrv != NULL) {
7072 if (!newsrv->puid) {
7073 /* server ID not set, use automatic numbering with first
7074 * spare entry starting with next_svid.
7075 */
7076 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7077 newsrv->conf.id.key = newsrv->puid = next_id;
7078 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7079 }
7080 next_id++;
7081 newsrv = newsrv->next;
7082 }
7083
Willy Tarreau20697042007-11-15 23:26:18 +01007084 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007085 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007086
Willy Tarreau62c3be22012-01-20 13:12:32 +01007087 /*
7088 * If this server supports a maxconn parameter, it needs a dedicated
7089 * tasks to fill the emptied slots when a connection leaves.
7090 * Also, resolve deferred tracking dependency if needed.
7091 */
7092 newsrv = curproxy->srv;
7093 while (newsrv != NULL) {
7094 if (newsrv->minconn > newsrv->maxconn) {
7095 /* Only 'minconn' was specified, or it was higher than or equal
7096 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7097 * this will avoid further useless expensive computations.
7098 */
7099 newsrv->maxconn = newsrv->minconn;
7100 } else if (newsrv->maxconn && !newsrv->minconn) {
7101 /* minconn was not specified, so we set it to maxconn */
7102 newsrv->minconn = newsrv->maxconn;
7103 }
7104
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007105#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007106 if (newsrv->use_ssl || newsrv->check.use_ssl)
7107 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007108#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007109
Willy Tarreau2f075e92013-12-03 11:11:34 +01007110 /* set the check type on the server */
7111 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7112
Willy Tarreau62c3be22012-01-20 13:12:32 +01007113 if (newsrv->trackit) {
7114 struct proxy *px;
7115 struct server *srv;
7116 char *pname, *sname;
7117
7118 pname = newsrv->trackit;
7119 sname = strrchr(pname, '/');
7120
7121 if (sname)
7122 *sname++ = '\0';
7123 else {
7124 sname = pname;
7125 pname = NULL;
7126 }
7127
7128 if (pname) {
7129 px = findproxy(pname, PR_CAP_BE);
7130 if (!px) {
7131 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7132 proxy_type_str(curproxy), curproxy->id,
7133 newsrv->id, pname);
7134 cfgerr++;
7135 goto next_srv;
7136 }
7137 } else
7138 px = curproxy;
7139
7140 srv = findserver(px, sname);
7141 if (!srv) {
7142 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7143 proxy_type_str(curproxy), curproxy->id,
7144 newsrv->id, sname);
7145 cfgerr++;
7146 goto next_srv;
7147 }
7148
Willy Tarreauff5ae352013-12-11 20:36:34 +01007149 if (!(srv->check.state & CHK_ST_CONFIGURED)) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007150 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
7151 "tracking as it does not have checks enabled.\n",
7152 proxy_type_str(curproxy), curproxy->id,
7153 newsrv->id, px->id, srv->id);
7154 cfgerr++;
7155 goto next_srv;
7156 }
7157
7158 if (curproxy != px &&
7159 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7160 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7161 "tracking: disable-on-404 option inconsistency.\n",
7162 proxy_type_str(curproxy), curproxy->id,
7163 newsrv->id, px->id, srv->id);
7164 cfgerr++;
7165 goto next_srv;
7166 }
7167
7168 /* if the other server is forced disabled, we have to do the same here */
7169 if (srv->state & SRV_MAINTAIN) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007170 newsrv->state &= ~SRV_RUNNING;
Simon Horman125d0992013-02-24 17:23:38 +09007171 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007172 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007173 }
7174
7175 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007176 newsrv->tracknext = srv->trackers;
7177 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007178
7179 free(newsrv->trackit);
7180 newsrv->trackit = NULL;
7181 }
7182 next_srv:
7183 newsrv = newsrv->next;
7184 }
7185
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007186 /* We have to initialize the server lookup mechanism depending
7187 * on what LB algorithm was choosen.
7188 */
7189
7190 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7191 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7192 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007193 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7194 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7195 init_server_map(curproxy);
7196 } else {
7197 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7198 fwrr_init_server_groups(curproxy);
7199 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007200 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007201
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007202 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007203 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7204 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7205 fwlc_init_server_tree(curproxy);
7206 } else {
7207 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7208 fas_init_server_tree(curproxy);
7209 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007210 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007211
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007212 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007213 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7214 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7215 chash_init_server_tree(curproxy);
7216 } else {
7217 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7218 init_server_map(curproxy);
7219 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007220 break;
7221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007222
7223 if (curproxy->options & PR_O_LOGASAP)
7224 curproxy->to_log &= ~LW_BYTES;
7225
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007226 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007227 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007228 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7229 proxy_type_str(curproxy), curproxy->id);
7230 err_code |= ERR_WARN;
7231 }
7232
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007233 if (curproxy->mode != PR_MODE_HTTP) {
7234 int optnum;
7235
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007236 if (curproxy->uri_auth) {
7237 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7238 proxy_type_str(curproxy), curproxy->id);
7239 err_code |= ERR_WARN;
7240 curproxy->uri_auth = NULL;
7241 }
7242
Willy Tarreau87cf5142011-08-19 22:57:24 +02007243 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007244 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7245 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7246 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007247 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007248 }
7249
7250 if (curproxy->options & PR_O_ORGTO) {
7251 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7252 "originalto", proxy_type_str(curproxy), curproxy->id);
7253 err_code |= ERR_WARN;
7254 curproxy->options &= ~PR_O_ORGTO;
7255 }
7256
7257 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7258 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7259 (curproxy->cap & cfg_opts[optnum].cap) &&
7260 (curproxy->options & cfg_opts[optnum].val)) {
7261 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7262 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7263 err_code |= ERR_WARN;
7264 curproxy->options &= ~cfg_opts[optnum].val;
7265 }
7266 }
7267
7268 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7269 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7270 (curproxy->cap & cfg_opts2[optnum].cap) &&
7271 (curproxy->options2 & cfg_opts2[optnum].val)) {
7272 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7273 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7274 err_code |= ERR_WARN;
7275 curproxy->options2 &= ~cfg_opts2[optnum].val;
7276 }
7277 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007278
Pieter Baauwd551fb52013-05-08 22:49:23 +02007279#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007280 if (curproxy->conn_src.bind_hdr_occ) {
7281 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007282 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007283 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007284 err_code |= ERR_WARN;
7285 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007286#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007287 }
7288
Willy Tarreaubaaee002006-06-26 02:48:02 +02007289 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007290 * ensure that we're not cross-dressing a TCP server into HTTP.
7291 */
7292 newsrv = curproxy->srv;
7293 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007294 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007295 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7296 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007297 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007298 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007299
Willy Tarreau0cec3312011-10-31 13:49:26 +01007300 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7301 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7302 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7303 err_code |= ERR_WARN;
7304 }
7305
Willy Tarreau82ffa392013-08-13 17:19:08 +02007306 if ((newsrv->state & SRV_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
7307 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7308 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7309 err_code |= ERR_WARN;
7310 }
7311
Pieter Baauwd551fb52013-05-08 22:49:23 +02007312#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007313 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7314 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007315 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 +01007316 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007317 err_code |= ERR_WARN;
7318 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007319#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007320 newsrv = newsrv->next;
7321 }
7322
Willy Tarreauc1a21672009-08-16 22:37:44 +02007323 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007324 if (!curproxy->accept)
7325 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007326
Willy Tarreauc1a21672009-08-16 22:37:44 +02007327 if (curproxy->tcp_req.inspect_delay ||
7328 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007329 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007330
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007331 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007332 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007333 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007334 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007335
7336 /* both TCP and HTTP must check switching rules */
7337 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7338 }
7339
7340 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007341 if (curproxy->tcp_req.inspect_delay ||
7342 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7343 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7344
Emeric Brun97679e72010-09-23 17:56:44 +02007345 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7346 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7347
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007348 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007349 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007350 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007351 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007352
7353 /* If the backend does requires RDP cookie persistence, we have to
7354 * enable the corresponding analyser.
7355 */
7356 if (curproxy->options2 & PR_O2_RDPC_PRST)
7357 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7358 }
7359
Emeric Brunc52962f2012-11-15 18:28:02 +01007360#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007361 /* Configure SSL for each bind line.
7362 * Note: if configuration fails at some point, the ->ctx member
7363 * remains NULL so that listeners can later detach.
7364 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007365 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Brunc52962f2012-11-15 18:28:02 +01007366 if (!bind_conf->is_ssl) {
7367 if (bind_conf->default_ctx) {
7368 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7369 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7370 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007371 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007372 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007373 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007374 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007375 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007376 cfgerr++;
7377 continue;
7378 }
7379
Emeric Brun4b3091e2012-09-24 15:48:52 +02007380 if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) {
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007381 Alert("Unable to allocate SSL session cache.\n");
7382 cfgerr++;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007383 continue;
7384 }
7385
Emeric Brunfc0421f2012-09-07 17:30:07 +02007386 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007387 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007388 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007389#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007390
Willy Tarreaue6b98942007-10-29 01:09:36 +01007391 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007392 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007393 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007394 if (!listener->luid) {
7395 /* listener ID not set, use automatic numbering with first
7396 * spare entry starting with next_luid.
7397 */
7398 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7399 listener->conf.id.key = listener->luid = next_id;
7400 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007401 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007402 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007403
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007404 /* enable separate counters */
7405 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7406 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007407 if (!listener->name)
7408 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007409 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007410
Willy Tarreaue6b98942007-10-29 01:09:36 +01007411 if (curproxy->options & PR_O_TCP_NOLING)
7412 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007413 if (!listener->maxconn)
7414 listener->maxconn = curproxy->maxconn;
7415 if (!listener->backlog)
7416 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007417 if (!listener->maxaccept)
7418 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7419
7420 /* we want to have an optimal behaviour on single process mode to
7421 * maximize the work at once, but in multi-process we want to keep
7422 * some fairness between processes, so we target half of the max
7423 * number of events to be balanced over all the processes the proxy
7424 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7425 * used to disable the limit.
7426 */
7427 if (listener->maxaccept > 0) {
7428 if (nbproc > 1)
7429 listener->maxaccept = (listener->maxaccept + 1) / 2;
7430 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7431 }
7432
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007433 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007434 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007435 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007436 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007437
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007438 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7439 listener->options |= LI_O_TCP_RULES;
7440
Willy Tarreaude3041d2010-05-31 10:56:17 +02007441 if (curproxy->mon_mask.s_addr)
7442 listener->options |= LI_O_CHK_MONNET;
7443
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007444 /* smart accept mode is automatic in HTTP mode */
7445 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007446 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007447 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7448 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007449 }
7450
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007451 /* Release unused SSL configs */
7452 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7453 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007454 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007455#ifdef USE_OPENSSL
7456 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007457 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007458 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007459 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007460 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007461#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007462 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007463
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007464 /* Check multi-process mode compatibility for the current proxy */
7465 if (global.nbproc > 1) {
7466 int nbproc = 0;
7467 if (curproxy->bind_proc) {
7468 int proc;
7469 for (proc = 0; proc < global.nbproc; proc++) {
7470 if (curproxy->bind_proc & (1 << proc)) {
7471 nbproc++;
7472 }
7473 }
7474 } else {
7475 nbproc = global.nbproc;
7476 }
7477 if (curproxy->table.peers.name) {
7478 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
7479 curproxy->id);
7480 cfgerr++;
7481 }
7482 if (nbproc > 1) {
7483 if (curproxy->uri_auth) {
7484 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
7485 curproxy->id);
7486 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7487 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7488 curproxy->id);
7489 }
7490 }
7491 if (curproxy->appsession_name) {
7492 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7493 curproxy->id);
7494 }
7495 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7496 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7497 curproxy->id);
7498 }
7499 }
7500 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007501
7502 /* create the task associated with the proxy */
7503 curproxy->task = task_new();
7504 if (curproxy->task) {
7505 curproxy->task->context = curproxy;
7506 curproxy->task->process = manage_proxy;
7507 /* no need to queue, it will be done automatically if some
7508 * listener gets limited.
7509 */
7510 curproxy->task->expire = TICK_ETERNITY;
7511 } else {
7512 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7513 curproxy->id);
7514 cfgerr++;
7515 }
7516
Willy Tarreaubaaee002006-06-26 02:48:02 +02007517 curproxy = curproxy->next;
7518 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007519
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007520 /* Check multi-process mode compatibility */
7521 if (global.nbproc > 1) {
Willy Tarreau35b7b162012-10-22 23:17:18 +02007522 if (global.stats_fe && !global.stats_fe->bind_proc) {
7523 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 +01007524 }
7525 }
7526
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007527 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
7528 struct auth_users *curuser;
7529 int g;
7530
7531 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
7532 unsigned int group_mask = 0;
7533 char *group = NULL;
7534
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007535 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007536 continue;
7537
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007538 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007539
7540 for (g = 0; g < curuserlist->grpcnt; g++)
7541 if (!strcmp(curuserlist->groups[g], group))
7542 break;
7543
7544 if (g == curuserlist->grpcnt) {
7545 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
7546 curuserlist->name, group, curuser->user);
7547 err_code |= ERR_ALERT | ERR_FATAL;
7548 goto out;
7549 }
7550
7551 group_mask |= (1 << g);
7552 }
7553
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007554 free(curuser->u.groups);
7555 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007556 }
7557
7558 for (g = 0; g < curuserlist->grpcnt; g++) {
7559 char *user = NULL;
7560
7561 if (!curuserlist->groupusers[g])
7562 continue;
7563
7564 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
7565 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
7566 if (!strcmp(curuser->user, user))
7567 break;
7568
7569 if (!curuser) {
7570 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
7571 curuserlist->name, user, curuserlist->groups[g]);
7572 err_code |= ERR_ALERT | ERR_FATAL;
7573 goto out;
7574 }
7575
Willy Tarreaub4c06b72010-02-02 11:28:20 +01007576 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007577 }
7578
7579 free(curuserlist->groupusers[g]);
7580 }
7581
7582 free(curuserlist->groupusers);
7583
7584#ifdef DEBUG_AUTH
7585 for (g = 0; g < curuserlist->grpcnt; g++) {
7586 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
7587
7588 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
Willy Tarreaub9509592012-05-10 23:25:35 +02007589 if (curuser->u.group_mask & (1 << g))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007590 fprintf(stderr, " %s", curuser->user);
7591 }
7592
7593 fprintf(stderr, "\n");
7594 }
7595#endif
7596
Willy Tarreaufbb78422011-06-05 15:38:35 +02007597 }
7598
7599 /* automatically compute fullconn if not set. We must not do it in the
7600 * loop above because cross-references are not yet fully resolved.
7601 */
7602 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7603 /* If <fullconn> is not set, let's set it to 10% of the sum of
7604 * the possible incoming frontend's maxconns.
7605 */
7606 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7607 struct proxy *fe;
7608 int total = 0;
7609
7610 /* sum up the number of maxconns of frontends which
7611 * reference this backend at least once or which are
7612 * the same one ('listen').
7613 */
7614 for (fe = proxy; fe; fe = fe->next) {
7615 struct switching_rule *rule;
7616 struct hdr_exp *exp;
7617 int found = 0;
7618
7619 if (!(fe->cap & PR_CAP_FE))
7620 continue;
7621
7622 if (fe == curproxy) /* we're on a "listen" instance */
7623 found = 1;
7624
7625 if (fe->defbe.be == curproxy) /* "default_backend" */
7626 found = 1;
7627
7628 /* check if a "use_backend" rule matches */
7629 if (!found) {
7630 list_for_each_entry(rule, &fe->switching_rules, list) {
7631 if (rule->be.backend == curproxy) {
7632 found = 1;
7633 break;
7634 }
7635 }
7636 }
7637
7638 /* check if a "reqsetbe" rule matches */
7639 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7640 if (exp->action == ACT_SETBE &&
7641 (struct proxy *)exp->replace == curproxy) {
7642 found = 1;
7643 break;
7644 }
7645 }
7646
7647 /* now we've checked all possible ways to reference a backend
7648 * from a frontend.
7649 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007650 if (!found)
7651 continue;
7652 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007653 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007654 /* we have the sum of the maxconns in <total>. We only
7655 * keep 10% of that sum to set the default fullconn, with
7656 * a hard minimum of 1 (to avoid a divide by zero).
7657 */
7658 curproxy->fullconn = (total + 9) / 10;
7659 if (!curproxy->fullconn)
7660 curproxy->fullconn = 1;
7661 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007662 }
7663
Willy Tarreau056f5682010-06-06 15:51:11 +02007664 /* initialize stick-tables on backend capable proxies. This must not
7665 * be done earlier because the data size may be discovered while parsing
7666 * other proxies.
7667 */
Godbach9703e662013-12-11 21:11:41 +08007668 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7669 if (!stktable_init(&curproxy->table)) {
7670 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7671 cfgerr++;
7672 }
7673 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007674
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007675 /*
7676 * Recount currently required checks.
7677 */
7678
7679 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7680 int optnum;
7681
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007682 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7683 if (curproxy->options & cfg_opts[optnum].val)
7684 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007685
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007686 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7687 if (curproxy->options2 & cfg_opts2[optnum].val)
7688 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007689 }
7690
Willy Tarreau122541c2011-09-07 21:24:49 +02007691 if (peers) {
7692 struct peers *curpeers = peers, **last;
7693 struct peer *p, *pb;
7694
7695 /* Remove all peers sections which don't have a valid listener.
7696 * This can happen when a peers section is never referenced and
7697 * does not contain a local peer.
7698 */
7699 last = &peers;
7700 while (*last) {
7701 curpeers = *last;
7702 if (curpeers->peers_fe) {
Willy Tarreauca57de32012-11-23 20:08:09 +01007703 LIST_NEXT(&curpeers->peers_fe->conf.listeners, struct listener *, by_fe)->maxaccept = 1;
Willy Tarreau122541c2011-09-07 21:24:49 +02007704 last = &curpeers->next;
7705 continue;
7706 }
7707
7708 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7709 curpeers->id, localpeer);
7710
7711 p = curpeers->remote;
7712 while (p) {
7713 pb = p->next;
7714 free(p->id);
7715 free(p);
7716 p = pb;
7717 }
7718
7719 /* Destroy and unlink this curpeers section.
7720 * Note: curpeers is backed up into *last.
7721 */
7722 free(curpeers->id);
7723 curpeers = curpeers->next;
7724 free(*last);
7725 *last = curpeers;
7726 }
7727 }
7728
Willy Tarreau34eb6712011-10-24 18:15:04 +02007729 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007730 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007731 MEM_F_SHARED);
7732
Willy Tarreaubb925012009-07-23 13:36:36 +02007733 if (cfgerr > 0)
7734 err_code |= ERR_ALERT | ERR_FATAL;
7735 out:
7736 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007737}
7738
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007739/*
7740 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7741 * parsing sessions.
7742 */
7743void cfg_register_keywords(struct cfg_kw_list *kwl)
7744{
7745 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7746}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007747
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007748/*
7749 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7750 */
7751void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7752{
7753 LIST_DEL(&kwl->list);
7754 LIST_INIT(&kwl->list);
7755}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007756
7757/*
7758 * Local variables:
7759 * c-indent-level: 8
7760 * c-basic-offset: 8
7761 * End:
7762 */