blob: a3ac66121ca4710ce0370d4fedc9ab4dee5e5ccc [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 Tarreaube1b9182009-06-14 18:48:19 +020026#include <netinet/tcp.h>
27
Willy Tarreau2dd0d472006-06-29 17:53:05 +020028#include <common/cfgparse.h>
29#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020030#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020031#include <common/memory.h>
32#include <common/standard.h>
33#include <common/time.h>
34#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
36#include <types/capture.h>
37#include <types/global.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020038#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020039
Willy Tarreaueb0c6142007-05-07 00:53:22 +020040#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010041#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010043#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020045#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020046#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020047#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020048#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010049#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020050#include <proto/lb_fwlc.h>
51#include <proto/lb_fwrr.h>
52#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010054#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020055#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010056#include <proto/protocols.h>
57#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020058#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010059#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010060#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020061#include <proto/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020062#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010063#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020064#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010065#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066
67
Willy Tarreauf3c69202006-07-09 16:42:34 +020068/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
69 * ssl-hello-chk option to ensure that the remote server speaks SSL.
70 *
71 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
72 */
73const char sslv3_client_hello_pkt[] = {
74 "\x16" /* ContentType : 0x16 = Hanshake */
75 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
76 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
77 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
78 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
79 "\x03\x00" /* Hello Version : 0x0300 = v3 */
80 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
81 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
82 "\x00" /* Session ID length : empty (no session ID) */
83 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
84 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
85 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
86 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
87 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
88 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
89 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
90 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
91 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
92 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
93 "\x00\x38" "\x00\x39" "\x00\x3A"
94 "\x01" /* Compression Length : 0x01 = 1 byte for types */
95 "\x00" /* Compression Type : 0x00 = NULL compression */
96};
97
Willy Tarreau3842f002009-06-14 11:39:52 +020098/* various keyword modifiers */
99enum kw_mod {
100 KWM_STD = 0, /* normal */
101 KWM_NO, /* "no" prefixed before the keyword */
102 KWM_DEF, /* "default" prefixed before the keyword */
103};
104
Willy Tarreau13943ab2006-12-31 00:24:10 +0100105/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100106struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100107 const char *name;
108 unsigned int val;
109 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100111 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100112};
113
114/* proxy->options */
115static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100116{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100117 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
118 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
119 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
120 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
121 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
122 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
123 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
124 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
125 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
126 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0, PR_MODE_HTTP },
127 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
128 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
129 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
130 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
131 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
132 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100133#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100134 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100135#else
136 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100137#endif
138
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100139 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140};
141
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142/* proxy->options2 */
143static const struct cfg_opt cfg_opts2[] =
144{
145#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100146 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
147 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
148 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100149#else
150 { "splice-request", 0, 0, 0, 0 },
151 { "splice-response", 0, 0, 0, 0 },
152 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100153#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
155 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
157 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
158 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
159 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
160 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
161 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
162 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
163 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200164 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200165 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100166 { NULL, 0, 0, 0 }
167};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200168
Willy Tarreau6daf3432008-01-22 16:44:08 +0100169static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
171int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100172int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200174/* List head of all known configuration keywords */
175static struct cfg_kw_list cfg_keywords = {
176 .list = LIST_HEAD_INIT(cfg_keywords.list)
177};
178
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179/*
180 * converts <str> to a list of listeners which are dynamically allocated.
181 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
182 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
183 * - <port> is a numerical port from 1 to 65535 ;
184 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
185 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200186 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100188static int str2listener(char *str, struct proxy *curproxy, const char *file, int line)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200189{
190 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100191 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200192 int port, end;
193
194 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200195
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 while (next && *next) {
197 struct sockaddr_storage ss;
198
199 str = next;
200 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100201 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 *next++ = 0;
203 }
204
Emeric Bruned760922010-10-22 17:59:25 +0200205 if (*str == '/') {
206 /* sun_path during a soft_stop rename is <unix_bind_prefix><path>.<pid>.<bak|tmp> */
207 /* so compute max path */
208 int prefix_path_len = global.unix_bind.prefix ? strlen(global.unix_bind.prefix) : 0;
209 int max_path_len = (sizeof(((struct sockaddr_un *)&ss)->sun_path) - 1) - (prefix_path_len + 1 + 5 + 1 + 3);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210
Emeric Bruned760922010-10-22 17:59:25 +0200211 if (strlen(str) > max_path_len) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100212 Alert("parsing [%s:%d] : socket path '%s' too long (max %d)\n",
213 file, line, str, max_path_len);
Emeric Bruned760922010-10-22 17:59:25 +0200214 goto fail;
215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200216
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 memset(&ss, 0, sizeof(ss));
Emeric Bruned760922010-10-22 17:59:25 +0200218 ss.ss_family = AF_UNIX;
219 if (global.unix_bind.prefix) {
220 memcpy(((struct sockaddr_un *)&ss)->sun_path, global.unix_bind.prefix, prefix_path_len);
221 strcpy(((struct sockaddr_un *)&ss)->sun_path+prefix_path_len, str);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 }
Emeric Bruned760922010-10-22 17:59:25 +0200223 else {
224 strcpy(((struct sockaddr_un *)&ss)->sun_path, str);
225 }
226 port = end = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 }
228 else {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100229 struct sockaddr_storage *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100231 ss2 = str2sa_range(str, &port, &end);
232 if (!ss2) {
233 Alert("parsing [%s:%d] : invalid listening address: '%s'\n",
234 file, line, str);
235 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100238 if (!port) {
239 Alert("parsing [%s:%d] : missing port number: '%s'\n",
240 file, line, str);
241 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200242 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100244 /* OK the address looks correct */
245 ss = *ss2;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
Emeric Bruned760922010-10-22 17:59:25 +0200247 if (port < 1 || port > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
249 file, line, port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200250 goto fail;
251 }
252
253 if (end < 1 || end > 65535) {
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100254 Alert("parsing [%s:%d] : invalid port '%d' specified for address '%s'.\n",
255 file, line, end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 }
259
260 for (; port <= end; port++) {
261 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200262 l->next = curproxy->listen;
263 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200264
265 l->fd = -1;
266 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100267 l->state = LI_INIT;
268
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100269 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100271 tcpv4_add_listener(l);
272 }
Emeric Bruned760922010-10-22 17:59:25 +0200273 else if (ss.ss_family == AF_INET6) {
274 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
275 tcpv6_add_listener(l);
276 }
277 else {
278 l->perm.ux.gid = l->perm.ux.uid = -1;
279 l->perm.ux.mode = 0;
280 uxst_add_listener(l);
281 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200282
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200283 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100284 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 } /* end for(port) */
286 } /* end while(next) */
287 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200288 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 fail:
290 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200291 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292}
293
Willy Tarreau977b8e42006-12-29 14:19:17 +0100294/*
295 * Sends a warning if proxy <proxy> does not have at least one of the
296 * capabilities in <cap>. An optionnal <hint> may be added at the end
297 * of the warning to help the user. Returns 1 if a warning was emitted
298 * or 0 if the condition is valid.
299 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100300int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint)
Willy Tarreau977b8e42006-12-29 14:19:17 +0100301{
302 char *msg;
303
304 switch (cap) {
305 case PR_CAP_BE: msg = "no backend"; break;
306 case PR_CAP_FE: msg = "no frontend"; break;
307 case PR_CAP_RS: msg = "no ruleset"; break;
308 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
309 default: msg = "not enough"; break;
310 }
311
312 if (!(proxy->cap & cap)) {
313 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100314 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100315 return 1;
316 }
317 return 0;
318}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319
Willy Tarreau61d18892009-03-31 10:49:21 +0200320/* Report a warning if a rule is placed after a 'block' rule.
321 * Return 1 if the warning has been emitted, otherwise 0.
322 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100323int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200324{
325 if (!LIST_ISEMPTY(&proxy->block_cond)) {
326 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
327 file, line, arg);
328 return 1;
329 }
330 return 0;
331}
332
333/* Report a warning if a rule is placed after a reqrewrite rule.
334 * Return 1 if the warning has been emitted, otherwise 0.
335 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100336int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200337{
338 if (proxy->req_exp) {
339 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
340 file, line, arg);
341 return 1;
342 }
343 return 0;
344}
345
346/* Report a warning if a rule is placed after a reqadd rule.
347 * Return 1 if the warning has been emitted, otherwise 0.
348 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100349int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200350{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100351 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200352 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
353 file, line, arg);
354 return 1;
355 }
356 return 0;
357}
358
359/* Report a warning if a rule is placed after a redirect rule.
360 * Return 1 if the warning has been emitted, otherwise 0.
361 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100362int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200363{
364 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
365 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
366 file, line, arg);
367 return 1;
368 }
369 return 0;
370}
371
372/* Report a warning if a rule is placed after a 'use_backend' rule.
373 * Return 1 if the warning has been emitted, otherwise 0.
374 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100375int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200376{
377 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
378 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
379 file, line, arg);
380 return 1;
381 }
382 return 0;
383}
384
385/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100386int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200387{
388 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
389 warnif_rule_after_reqadd(proxy, file, line, arg) ||
390 warnif_rule_after_redirect(proxy, file, line, arg) ||
391 warnif_rule_after_use_backend(proxy, file, line, arg);
392}
393
394/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100395int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200396{
397 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
398 warnif_rule_after_redirect(proxy, file, line, arg) ||
399 warnif_rule_after_use_backend(proxy, file, line, arg);
400}
401
402/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 return warnif_rule_after_redirect(proxy, file, line, arg) ||
406 warnif_rule_after_use_backend(proxy, file, line, arg);
407}
408
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100409/* Report it if a request ACL condition uses some response-only parameters. It
410 * returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
411 * Note that <cond> may be NULL and then will be ignored.
412 */
413static int warnif_cond_requires_resp(const struct acl_cond *cond, const char *file, int line)
414{
415 struct acl *acl;
416
417 if (!cond || !(cond->requires & ACL_USE_RTR_ANY))
418 return 0;
419
420 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
421 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
422 file, line, acl ? acl->name : "(unknown)");
423 return ERR_WARN;
424}
425
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100426/* Report it if a request ACL condition uses some request-only volatile parameters.
427 * It returns either 0 or ERR_WARN so that its result can be or'ed with err_code.
428 * Note that <cond> may be NULL and then will be ignored.
429 */
430static int warnif_cond_requires_req(const struct acl_cond *cond, const char *file, int line)
431{
432 struct acl *acl;
433
434 if (!cond || !(cond->requires & ACL_USE_REQ_VOLATILE))
435 return 0;
436
437 acl = cond_find_require(cond, ACL_USE_REQ_VOLATILE);
438 Warning("parsing [%s:%d] : acl '%s' involves some volatile request-only criteria which will be ignored.\n",
439 file, line, acl ? acl->name : "(unknown)");
440 return ERR_WARN;
441}
442
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100443
Willy Tarreaubaaee002006-06-26 02:48:02 +0200444/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200445 * parse a line in a <global> section. Returns the error code, 0 if OK, or
446 * any combination of :
447 * - ERR_ABORT: must abort ASAP
448 * - ERR_FATAL: we can continue parsing but not start the service
449 * - ERR_WARN: a warning has been emitted
450 * - ERR_ALERT: an alert has been emitted
451 * Only the two first ones can stop processing, the two others are just
452 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200453 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200454int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200455{
Willy Tarreau058e9072009-07-20 09:30:05 +0200456 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200457
458 if (!strcmp(args[0], "global")) { /* new section */
459 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200461 }
462 else if (!strcmp(args[0], "daemon")) {
463 global.mode |= MODE_DAEMON;
464 }
465 else if (!strcmp(args[0], "debug")) {
466 global.mode |= MODE_DEBUG;
467 }
468 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100469 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200470 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200471 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100472 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200473 }
474 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100475 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100478 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200479 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100480 else if (!strcmp(args[0], "nosplice")) {
481 global.tune.options &= ~GTUNE_USE_SPLICE;
482 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200483 else if (!strcmp(args[0], "quiet")) {
484 global.mode |= MODE_QUIET;
485 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200486 else if (!strcmp(args[0], "tune.maxpollevents")) {
487 if (global.tune.maxpollevents != 0) {
488 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200489 err_code |= ERR_ALERT;
490 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200491 }
492 if (*(args[1]) == 0) {
493 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200494 err_code |= ERR_ALERT | ERR_FATAL;
495 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200496 }
497 global.tune.maxpollevents = atol(args[1]);
498 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100499 else if (!strcmp(args[0], "tune.maxaccept")) {
500 if (global.tune.maxaccept != 0) {
501 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200502 err_code |= ERR_ALERT;
503 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100504 }
505 if (*(args[1]) == 0) {
506 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200507 err_code |= ERR_ALERT | ERR_FATAL;
508 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100509 }
510 global.tune.maxaccept = atol(args[1]);
511 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200512 else if (!strcmp(args[0], "tune.chksize")) {
513 if (*(args[1]) == 0) {
514 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
515 err_code |= ERR_ALERT | ERR_FATAL;
516 goto out;
517 }
518 global.tune.chksize = atol(args[1]);
519 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200520 else if (!strcmp(args[0], "tune.bufsize")) {
521 if (*(args[1]) == 0) {
522 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
523 err_code |= ERR_ALERT | ERR_FATAL;
524 goto out;
525 }
526 global.tune.bufsize = atol(args[1]);
527 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
528 global.tune.maxrewrite = global.tune.bufsize / 2;
529 }
530 else if (!strcmp(args[0], "tune.maxrewrite")) {
531 if (*(args[1]) == 0) {
532 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
533 err_code |= ERR_ALERT | ERR_FATAL;
534 goto out;
535 }
536 global.tune.maxrewrite = atol(args[1]);
537 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
538 global.tune.maxrewrite = global.tune.bufsize / 2;
539 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100540 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
541 if (global.tune.client_rcvbuf != 0) {
542 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
543 err_code |= ERR_ALERT;
544 goto out;
545 }
546 if (*(args[1]) == 0) {
547 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
548 err_code |= ERR_ALERT | ERR_FATAL;
549 goto out;
550 }
551 global.tune.client_rcvbuf = atol(args[1]);
552 }
553 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
554 if (global.tune.server_rcvbuf != 0) {
555 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
556 err_code |= ERR_ALERT;
557 goto out;
558 }
559 if (*(args[1]) == 0) {
560 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564 global.tune.server_rcvbuf = atol(args[1]);
565 }
566 else if (!strcmp(args[0], "tune.sndbuf.client")) {
567 if (global.tune.client_sndbuf != 0) {
568 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
569 err_code |= ERR_ALERT;
570 goto out;
571 }
572 if (*(args[1]) == 0) {
573 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
574 err_code |= ERR_ALERT | ERR_FATAL;
575 goto out;
576 }
577 global.tune.client_sndbuf = atol(args[1]);
578 }
579 else if (!strcmp(args[0], "tune.sndbuf.server")) {
580 if (global.tune.server_sndbuf != 0) {
581 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
582 err_code |= ERR_ALERT;
583 goto out;
584 }
585 if (*(args[1]) == 0) {
586 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
587 err_code |= ERR_ALERT | ERR_FATAL;
588 goto out;
589 }
590 global.tune.server_sndbuf = atol(args[1]);
591 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200592 else if (!strcmp(args[0], "tune.pipesize")) {
593 if (*(args[1]) == 0) {
594 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
595 err_code |= ERR_ALERT | ERR_FATAL;
596 goto out;
597 }
598 global.tune.pipesize = atol(args[1]);
599 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200600 else if (!strcmp(args[0], "tune.http.maxhdr")) {
601 if (*(args[1]) == 0) {
602 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605 }
606 global.tune.max_http_hdr = atol(args[1]);
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "uid")) {
609 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200610 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200611 err_code |= ERR_ALERT;
612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 }
614 if (*(args[1]) == 0) {
615 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200616 err_code |= ERR_ALERT | ERR_FATAL;
617 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200618 }
619 global.uid = atol(args[1]);
620 }
621 else if (!strcmp(args[0], "gid")) {
622 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200623 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200624 err_code |= ERR_ALERT;
625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 }
627 if (*(args[1]) == 0) {
628 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200629 err_code |= ERR_ALERT | ERR_FATAL;
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 }
632 global.gid = atol(args[1]);
633 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200634 /* user/group name handling */
635 else if (!strcmp(args[0], "user")) {
636 struct passwd *ha_user;
637 if (global.uid != 0) {
638 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200639 err_code |= ERR_ALERT;
640 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200641 }
642 errno = 0;
643 ha_user = getpwnam(args[1]);
644 if (ha_user != NULL) {
645 global.uid = (int)ha_user->pw_uid;
646 }
647 else {
648 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 +0200649 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200650 }
651 }
652 else if (!strcmp(args[0], "group")) {
653 struct group *ha_group;
654 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200655 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200656 err_code |= ERR_ALERT;
657 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200658 }
659 errno = 0;
660 ha_group = getgrnam(args[1]);
661 if (ha_group != NULL) {
662 global.gid = (int)ha_group->gr_gid;
663 }
664 else {
665 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 +0200666 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200667 }
668 }
669 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 else if (!strcmp(args[0], "nbproc")) {
671 if (global.nbproc != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200680 }
681 global.nbproc = atol(args[1]);
682 }
683 else if (!strcmp(args[0], "maxconn")) {
684 if (global.maxconn != 0) {
685 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200686 err_code |= ERR_ALERT;
687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200688 }
689 if (*(args[1]) == 0) {
690 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200691 err_code |= ERR_ALERT | ERR_FATAL;
692 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200693 }
694 global.maxconn = atol(args[1]);
695#ifdef SYSTEM_MAXCONN
696 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
697 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);
698 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200699 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200700 }
701#endif /* SYSTEM_MAXCONN */
702 }
Willy Tarreau81c25d02011-09-07 15:17:21 +0200703 else if (!strcmp(args[0], "maxconnrate")) {
704 if (global.cps_lim != 0) {
705 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
706 err_code |= ERR_ALERT;
707 goto out;
708 }
709 if (*(args[1]) == 0) {
710 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
711 err_code |= ERR_ALERT | ERR_FATAL;
712 goto out;
713 }
714 global.cps_lim = atol(args[1]);
715 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100716 else if (!strcmp(args[0], "maxpipes")) {
717 if (global.maxpipes != 0) {
718 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200719 err_code |= ERR_ALERT;
720 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100721 }
722 if (*(args[1]) == 0) {
723 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100726 }
727 global.maxpipes = atol(args[1]);
728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200729 else if (!strcmp(args[0], "ulimit-n")) {
730 if (global.rlimit_nofile != 0) {
731 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200732 err_code |= ERR_ALERT;
733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200734 }
735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200739 }
740 global.rlimit_nofile = atol(args[1]);
741 }
742 else if (!strcmp(args[0], "chroot")) {
743 if (global.chroot != NULL) {
744 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT;
746 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 if (*(args[1]) == 0) {
749 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200750 err_code |= ERR_ALERT | ERR_FATAL;
751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200752 }
753 global.chroot = strdup(args[1]);
754 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200755 else if (!strcmp(args[0], "description")) {
756 int i, len=0;
757 char *d;
758
759 if (!*args[1]) {
760 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
761 file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 for(i=1; *args[i]; i++)
767 len += strlen(args[i])+1;
768
769 if (global.desc)
770 free(global.desc);
771
772 global.desc = d = (char *)calloc(1, len);
773
774 d += sprintf(d, "%s", args[1]);
775 for(i=2; *args[i]; i++)
776 d += sprintf(d, " %s", args[i]);
777 }
778 else if (!strcmp(args[0], "node")) {
779 int i;
780 char c;
781
782 for (i=0; args[1][i]; i++) {
783 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +0100784 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
785 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200786 break;
787 }
788
789 if (!i || args[1][i]) {
790 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
791 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
792 file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796
797 if (global.node)
798 free(global.node);
799
800 global.node = strdup(args[1]);
801 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200802 else if (!strcmp(args[0], "pidfile")) {
803 if (global.pidfile != NULL) {
804 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200805 err_code |= ERR_ALERT;
806 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200807 }
808 if (*(args[1]) == 0) {
809 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200810 err_code |= ERR_ALERT | ERR_FATAL;
811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200812 }
813 global.pidfile = strdup(args[1]);
814 }
Emeric Bruned760922010-10-22 17:59:25 +0200815 else if (!strcmp(args[0], "unix-bind")) {
816 int cur_arg = 1;
817 while (*(args[cur_arg])) {
818 if (!strcmp(args[cur_arg], "prefix")) {
819 if (global.unix_bind.prefix != NULL) {
820 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
821 err_code |= ERR_ALERT;
822 cur_arg += 2;
823 continue;
824 }
825
826 if (*(args[cur_arg+1]) == 0) {
827 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 global.unix_bind.prefix = strdup(args[cur_arg+1]);
832 cur_arg += 2;
833 continue;
834 }
835
836 if (!strcmp(args[cur_arg], "mode")) {
837
838 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
839 cur_arg += 2;
840 continue;
841 }
842
843 if (!strcmp(args[cur_arg], "uid")) {
844
845 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
846 cur_arg += 2;
847 continue;
848 }
849
850 if (!strcmp(args[cur_arg], "gid")) {
851
852 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
853 cur_arg += 2;
854 continue;
855 }
856
857 if (!strcmp(args[cur_arg], "user")) {
858 struct passwd *user;
859
860 user = getpwnam(args[cur_arg + 1]);
861 if (!user) {
862 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
863 file, linenum, args[0], args[cur_arg + 1 ]);
864 err_code |= ERR_ALERT | ERR_FATAL;
865 goto out;
866 }
867
868 global.unix_bind.ux.uid = user->pw_uid;
869 cur_arg += 2;
870 continue;
871 }
872
873 if (!strcmp(args[cur_arg], "group")) {
874 struct group *group;
875
876 group = getgrnam(args[cur_arg + 1]);
877 if (!group) {
878 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
879 file, linenum, args[0], args[cur_arg + 1 ]);
880 err_code |= ERR_ALERT | ERR_FATAL;
881 goto out;
882 }
883
884 global.unix_bind.ux.gid = group->gr_gid;
885 cur_arg += 2;
886 continue;
887 }
888
Willy Tarreaub48f9582011-09-05 01:17:06 +0200889 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +0200890 file, linenum, args[0]);
891 err_code |= ERR_ALERT | ERR_FATAL;
892 goto out;
893 }
894 }
William Lallemand0f99e342011-10-12 17:50:54 +0200895 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
896 /* delete previous herited or defined syslog servers */
897 struct logsrv *back;
898 struct logsrv *tmp;
899
900 if (*(args[1]) != 0) {
901 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
902 err_code |= ERR_ALERT | ERR_FATAL;
903 goto out;
904 }
905
906 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
907 LIST_DEL(&tmp->list);
908 free(tmp);
909 }
910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +0200912 struct logsrv *logsrv;
913
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 if (*(args[1]) == 0 || *(args[2]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
William Lallemand0f99e342011-10-12 17:50:54 +0200919
920 logsrv = calloc(1, sizeof(struct logsrv));
921
922 logsrv->facility = get_log_facility(args[2]);
923 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200926 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928
William Lallemand0f99e342011-10-12 17:50:54 +0200929 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200931 logsrv->level = get_log_level(args[3]);
932 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200933 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200934 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200935 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
937 }
938
William Lallemand0f99e342011-10-12 17:50:54 +0200939 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200940 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +0200941 logsrv->minlvl = get_log_level(args[4]);
942 if (logsrv->minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200943 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200945 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200946 }
947 }
948
Robert Tsai81ae1952007-12-05 10:47:29 +0100949 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +0100950 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100951 if (!sk) {
952 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +0100953 args[1], (int)sizeof(((struct sockaddr_un *)&sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100954 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200955 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100956 goto out;
957 }
William Lallemand0f99e342011-10-12 17:50:54 +0200958 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +0100959 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +0100960 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +0100961 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +0100962 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
963 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +0200964 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +0100965 goto out;
966 }
William Lallemand0f99e342011-10-12 17:50:54 +0200967 logsrv->addr = *sk;
968 if (!get_host_port(&logsrv->addr))
969 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +0100970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971
William Lallemand0f99e342011-10-12 17:50:54 +0200972 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200973 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +0100974 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
975 char *name;
976 int len;
977
978 if (global.log_send_hostname != NULL) {
979 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
980 err_code |= ERR_ALERT;
981 goto out;
982 }
983
984 if (*(args[1]))
985 name = args[1];
986 else
987 name = hostname;
988
989 len = strlen(name);
990
991 /* We'll add a space after the name to respect the log format */
992 free(global.log_send_hostname);
993 global.log_send_hostname = malloc(len + 2);
994 snprintf(global.log_send_hostname, len + 2, "%s ", name);
995 }
Kevinm48936af2010-12-22 16:08:21 +0000996 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 free(global.log_tag);
1003 global.log_tag = strdup(args[1]);
1004 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001005 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1006 if (global.spread_checks != 0) {
1007 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001008 err_code |= ERR_ALERT;
1009 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001010 }
1011 if (*(args[1]) == 0) {
1012 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001015 }
1016 global.spread_checks = atol(args[1]);
1017 if (global.spread_checks < 0 || global.spread_checks > 50) {
1018 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001019 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001021 }
1022 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001023 struct cfg_kw_list *kwl;
1024 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001025 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001026
1027 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1028 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1029 if (kwl->kw[index].section != CFG_GLOBAL)
1030 continue;
1031 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
1032 /* prepare error message just in case */
1033 snprintf(trash, sizeof(trash),
1034 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +02001035 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
1036 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001037 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001038 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001039 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001040 else if (rc > 0) {
1041 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +02001042 err_code |= ERR_WARN;
1043 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001044 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001045 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001046 }
1047 }
1048 }
1049
Willy Tarreaubaaee002006-06-26 02:48:02 +02001050 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001053
Willy Tarreau058e9072009-07-20 09:30:05 +02001054 out:
1055 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001056}
1057
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001058void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001059{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001060 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061 defproxy.mode = PR_MODE_TCP;
1062 defproxy.state = PR_STNEW;
1063 defproxy.maxconn = cfg_maxpconn;
1064 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001065
1066 defproxy.defsrv.inter = DEF_CHKINTR;
1067 defproxy.defsrv.fastinter = 0;
1068 defproxy.defsrv.downinter = 0;
1069 defproxy.defsrv.rise = DEF_RISETIME;
1070 defproxy.defsrv.fall = DEF_FALLTIME;
1071 defproxy.defsrv.check_port = 0;
1072 defproxy.defsrv.maxqueue = 0;
1073 defproxy.defsrv.minconn = 0;
1074 defproxy.defsrv.maxconn = 0;
1075 defproxy.defsrv.slowstart = 0;
1076 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1077 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1078 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079}
1080
Willy Tarreauade5ec42010-01-28 19:33:49 +01001081
1082static int create_cond_regex_rule(const char *file, int line,
1083 struct proxy *px, int dir, int action, int flags,
1084 const char *cmd, const char *reg, const char *repl,
1085 const char **cond_start)
1086{
1087 regex_t *preg = NULL;
1088 const char *err;
1089 int err_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001090 struct acl_cond *cond = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001091
1092 if (px == &defproxy) {
1093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto err;
1096 }
1097
1098 if (*reg == 0) {
1099 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
1100 err_code |= ERR_ALERT | ERR_FATAL;
1101 goto err;
1102 }
1103
1104 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
1105 err_code |= ERR_WARN;
1106
Willy Tarreau5321c422010-01-28 20:35:13 +01001107 if (cond_start &&
1108 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
1109 if ((cond = build_acl_cond(file, line, px, cond_start)) == NULL) {
1110 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
1111 file, line, cmd);
1112 err_code |= ERR_ALERT | ERR_FATAL;
1113 goto err;
1114 }
1115 }
1116 else if (cond_start && **cond_start) {
1117 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1118 file, line, cmd, *cond_start);
1119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto err;
1121 }
1122
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001123 if (dir == SMP_OPT_DIR_REQ)
Willy Tarreau5321c422010-01-28 20:35:13 +01001124 err_code |= warnif_cond_requires_resp(cond, file, line);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01001125 else
1126 err_code |= warnif_cond_requires_req(cond, file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001127
Willy Tarreauade5ec42010-01-28 19:33:49 +01001128 preg = calloc(1, sizeof(regex_t));
1129 if (!preg) {
1130 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
1131 err_code = ERR_ALERT | ERR_FATAL;
1132 goto err;
1133 }
1134
1135 if (regcomp(preg, reg, REG_EXTENDED | flags) != 0) {
1136 Alert("parsing [%s:%d] : '%s' : bad regular expression '%s'.\n", file, line, cmd, reg);
1137 err_code = ERR_ALERT | ERR_FATAL;
1138 goto err;
1139 }
1140
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001141 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001142 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001143 if (repl && err) {
1144 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1145 file, line, cmd, *err);
1146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto err;
1148 }
1149
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001150 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreauade5ec42010-01-28 19:33:49 +01001151 err_code |= ERR_WARN;
1152
1153 return err_code;
1154 err:
1155 free(preg);
1156 return err_code;
1157}
1158
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001160 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001161 * Returns the error code, 0 if OK, or any combination of :
1162 * - ERR_ABORT: must abort ASAP
1163 * - ERR_FATAL: we can continue parsing but not start the service
1164 * - ERR_WARN: a warning has been emitted
1165 * - ERR_ALERT: an alert has been emitted
1166 * Only the two first ones can stop processing, the two others are just
1167 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001169int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1170{
1171 static struct peers *curpeers = NULL;
1172 struct peer *newpeer = NULL;
1173 const char *err;
1174 int err_code = 0;
1175
1176 if (strcmp(args[0], "peers") == 0) { /* new peers section */
1177
1178 err = invalid_char(args[1]);
1179 if (err) {
1180 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1181 file, linenum, *err, args[0], args[1]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 }
1184
1185 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1186 /*
1187 * If there are two proxies with the same name only following
1188 * combinations are allowed:
1189 */
1190 if (strcmp(curpeers->id, args[1]) == 0) {
1191 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1192 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1193 err_code |= ERR_WARN;
1194 }
1195 }
1196
1197 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1198 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1199 err_code |= ERR_ALERT | ERR_ABORT;
1200 goto out;
1201 }
1202
1203 curpeers->next = peers;
1204 peers = curpeers;
1205 curpeers->conf.file = file;
1206 curpeers->conf.line = linenum;
1207 curpeers->last_change = now.tv_sec;
1208 curpeers->id = strdup(args[1]);
1209 }
1210 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
1211 char *rport, *raddr;
1212 short realport = 0;
David du Colombier6f5ccb12011-03-10 22:26:24 +01001213 struct sockaddr_storage *sk;
Emeric Brun32da3c42010-09-23 18:39:19 +02001214
1215 if (!*args[2]) {
1216 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1217 file, linenum, args[0]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221
1222 err = invalid_char(args[1]);
1223 if (err) {
1224 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1225 file, linenum, *err, args[1]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229
1230 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1231 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1232 err_code |= ERR_ALERT | ERR_ABORT;
1233 goto out;
1234 }
1235
1236 /* the peers are linked backwards first */
1237 curpeers->count++;
1238 newpeer->next = curpeers->remote;
1239 curpeers->remote = newpeer;
1240 newpeer->peers = curpeers;
1241 newpeer->conf.file = file;
1242 newpeer->conf.line = linenum;
1243
1244 newpeer->last_change = now.tv_sec;
1245 newpeer->id = strdup(args[1]);
1246
1247 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01001248 rport = strrchr(raddr, ':');
Emeric Brun32da3c42010-09-23 18:39:19 +02001249 if (rport) {
1250 *rport++ = 0;
1251 realport = atol(rport);
1252 }
1253 if (!realport) {
1254 Alert("parsing [%s:%d] : Missing or invalid port in '%s'\n", file, linenum, args[2]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258
Willy Tarreaufab5a432011-03-04 15:31:53 +01001259 sk = str2ip(raddr);
Emeric Brun32da3c42010-09-23 18:39:19 +02001260 free(raddr);
1261 if (!sk) {
1262 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
1263 err_code |= ERR_ALERT | ERR_FATAL;
1264 goto out;
1265 }
1266 newpeer->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02001267 set_host_port(&newpeer->addr, realport);
Emeric Brun32da3c42010-09-23 18:39:19 +02001268
1269 if (strcmp(newpeer->id, localpeer) == 0) {
1270 /* Current is local peer, it define a frontend */
1271 newpeer->local = 1;
1272
1273 if (!curpeers->peers_fe) {
1274 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1275 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1276 err_code |= ERR_ALERT | ERR_ABORT;
1277 goto out;
1278 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001279
Willy Tarreau237250c2011-07-29 01:49:03 +02001280 init_new_proxy(curpeers->peers_fe);
1281 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001282
1283 curpeers->peers_fe->last_change = now.tv_sec;
1284 curpeers->peers_fe->id = strdup(args[1]);
1285 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001286 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001287 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1288 curpeers->peers_fe->timeout.connect = 5000;
1289 curpeers->peers_fe->accept = peer_accept;
1290 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001291 if (!str2listener(args[2], curpeers->peers_fe, file, linenum)) {
Emeric Brun32da3c42010-09-23 18:39:19 +02001292 err_code |= ERR_FATAL;
1293 goto out;
1294 }
1295 curpeers->peers_fe->listen->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1296 curpeers->peers_fe->listen->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1297 curpeers->peers_fe->listen->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1298 curpeers->peers_fe->listen->accept = session_accept;
1299 curpeers->peers_fe->listen->frontend = ((struct proxy *)curpeers->peers_fe);
1300 curpeers->peers_fe->listen->handler = process_session;
1301 curpeers->peers_fe->listen->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau3c63fd82011-09-07 18:00:47 +02001302 curpeers->peers_fe->listen->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1303 global.maxsock += curpeers->peers_fe->listen->maxconn;
Emeric Brun32da3c42010-09-23 18:39:19 +02001304 }
1305 }
1306 } /* neither "peer" nor "peers" */
1307 else if (*args[0] != 0) {
1308 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
1311 }
1312
1313out:
1314 return err_code;
1315}
1316
1317
Willy Tarreau3842f002009-06-14 11:39:52 +02001318int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319{
1320 static struct proxy *curproxy = NULL;
1321 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001322 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001323 int rc;
1324 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001325 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001326 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001327 struct logsrv *tmplogsrv;
1328 struct logformat_node *tmplf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001329
Willy Tarreau977b8e42006-12-29 14:19:17 +01001330 if (!strcmp(args[0], "listen"))
1331 rc = PR_CAP_LISTEN;
1332 else if (!strcmp(args[0], "frontend"))
1333 rc = PR_CAP_FE | PR_CAP_RS;
1334 else if (!strcmp(args[0], "backend"))
1335 rc = PR_CAP_BE | PR_CAP_RS;
1336 else if (!strcmp(args[0], "ruleset"))
1337 rc = PR_CAP_RS;
1338 else
1339 rc = PR_CAP_NONE;
1340
1341 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 if (!*args[1]) {
1343 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1344 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1345 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001346 err_code |= ERR_ALERT | ERR_ABORT;
1347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001348 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001349
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001350 err = invalid_char(args[1]);
1351 if (err) {
1352 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1353 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001354 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001355 }
1356
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001357 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
1358 /*
1359 * If there are two proxies with the same name only following
1360 * combinations are allowed:
1361 *
1362 * listen backend frontend ruleset
1363 * listen - - - -
1364 * backend - - OK -
1365 * frontend - OK - -
1366 * ruleset - - - -
1367 */
1368
1369 if (!strcmp(curproxy->id, args[1]) &&
1370 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
1371 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001372 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1373 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1374 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001375 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001376 }
1377 }
1378
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1380 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001381 err_code |= ERR_ALERT | ERR_ABORT;
1382 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001384
Willy Tarreau97cb7802010-01-03 20:23:58 +01001385 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001386 curproxy->next = proxy;
1387 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001388 curproxy->conf.file = file;
1389 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001390 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001391 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001392 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001393
1394 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001395 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +02001396 struct listener *new, *last = curproxy->listen;
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001397 if (!str2listener(args[2], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001398 err_code |= ERR_FATAL;
1399 goto out;
1400 }
Willy Tarreau90a570f2009-10-04 20:54:54 +02001401 new = curproxy->listen;
1402 while (new != last) {
1403 new->conf.file = file;
1404 new->conf.line = linenum;
1405 new = new->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001406 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001407 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001408 }
1409
1410 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001411 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001412 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001413
Willy Tarreaubaaee002006-06-26 02:48:02 +02001414 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001415 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01001416 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02001417 curproxy->no_options = defproxy.no_options;
1418 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001419 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +01001420 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02001421 curproxy->except_net = defproxy.except_net;
1422 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02001423 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02001424 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001426 if (defproxy.fwdfor_hdr_len) {
1427 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1428 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1429 }
1430
Willy Tarreaub86db342009-11-30 11:50:16 +01001431 if (defproxy.orgto_hdr_len) {
1432 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1433 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1434 }
1435
Mark Lamourinec2247f02012-01-04 13:02:01 -05001436 if (defproxy.server_id_hdr_len) {
1437 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
1438 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
1439 }
1440
Willy Tarreau977b8e42006-12-29 14:19:17 +01001441 if (curproxy->cap & PR_CAP_FE) {
1442 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001443 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001444 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001445
1446 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001447 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1448 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001449
1450 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452
Willy Tarreau977b8e42006-12-29 14:19:17 +01001453 if (curproxy->cap & PR_CAP_BE) {
1454 curproxy->fullconn = defproxy.fullconn;
1455 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456
Willy Tarreauaa2f3892010-10-22 16:15:31 +02001457 if (defproxy.check_req) {
1458 curproxy->check_req = calloc(1, defproxy.check_len);
1459 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
1460 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001461 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001463 if (defproxy.expect_str) {
1464 curproxy->expect_str = strdup(defproxy.expect_str);
1465 if (defproxy.expect_regex) {
1466 /* note: this regex is known to be valid */
1467 curproxy->expect_regex = calloc(1, sizeof(regex_t));
1468 regcomp(curproxy->expect_regex, defproxy.expect_str, REG_EXTENDED);
1469 }
1470 }
1471
Willy Tarreau977b8e42006-12-29 14:19:17 +01001472 if (defproxy.cookie_name)
1473 curproxy->cookie_name = strdup(defproxy.cookie_name);
1474 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001475 if (defproxy.cookie_domain)
1476 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001477
Willy Tarreau31936852010-10-06 16:59:56 +02001478 if (defproxy.cookie_maxidle)
1479 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
1480
1481 if (defproxy.cookie_maxlife)
1482 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
1483
Emeric Brun647caf12009-06-30 17:57:00 +02001484 if (defproxy.rdp_cookie_name)
1485 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1486 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1487
Willy Tarreau01732802007-11-01 22:48:15 +01001488 if (defproxy.url_param_name)
1489 curproxy->url_param_name = strdup(defproxy.url_param_name);
1490 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001491
Benoitaffb4812009-03-25 13:02:10 +01001492 if (defproxy.hh_name)
1493 curproxy->hh_name = strdup(defproxy.hh_name);
1494 curproxy->hh_len = defproxy.hh_len;
1495 curproxy->hh_match_domain = defproxy.hh_match_domain;
1496
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001497 if (defproxy.iface_name)
1498 curproxy->iface_name = strdup(defproxy.iface_name);
1499 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001502 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001503 if (defproxy.capture_name)
1504 curproxy->capture_name = strdup(defproxy.capture_name);
1505 curproxy->capture_namelen = defproxy.capture_namelen;
1506 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508
Willy Tarreau977b8e42006-12-29 14:19:17 +01001509 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001510 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001511 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001512 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001513 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001514 curproxy->uri_auth = defproxy.uri_auth;
1515 curproxy->mon_net = defproxy.mon_net;
1516 curproxy->mon_mask = defproxy.mon_mask;
1517 if (defproxy.monitor_uri)
1518 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1519 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001520 if (defproxy.defbe.name)
1521 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001522 }
1523
1524 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001525 curproxy->timeout.connect = defproxy.timeout.connect;
1526 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001527 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001528 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001529 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001530 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001531 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001532 curproxy->source_addr = defproxy.source_addr;
1533 }
1534
Willy Tarreaubaaee002006-06-26 02:48:02 +02001535 curproxy->mode = defproxy.mode;
William Lallemand0f99e342011-10-12 17:50:54 +02001536
1537 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01001538 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02001539 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01001540 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001541 LIST_INIT(&node->list);
1542 LIST_ADDQ(&curproxy->logsrvs, &node->list);
1543 }
1544
William Lallemand723b73a2012-02-08 16:37:49 +01001545 /* copy default log_format to curproxy */
1546 list_for_each_entry(tmplf, &defproxy.logformat, list) {
1547 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1548 memcpy(node, tmplf, sizeof(struct logformat_node));
1549 LIST_INIT(&node->list);
1550 LIST_ADDQ(&curproxy->logformat, &node->list);
1551 }
1552
William Lallemanda73203e2012-03-12 12:48:57 +01001553 /* copy default unique_id to curproxy */
1554 list_for_each_entry(tmplf, &defproxy.format_unique_id, list) {
1555 struct logformat_node *node = malloc(sizeof(struct logformat_node));
1556 memcpy(node, tmplf, sizeof(struct logformat_node));
1557 LIST_INIT(&node->list);
1558 LIST_ADDQ(&curproxy->format_unique_id, &node->list);
1559 }
1560
1561 /* copy default header unique id */
1562 if (defproxy.header_unique_id)
1563 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
1564
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001566 curproxy->conf.used_listener_id = EB_ROOT;
1567 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001568
Willy Tarreau93893792009-07-23 13:19:11 +02001569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 }
1571 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1572 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001573 /* FIXME-20070101: we should do this too at the end of the
1574 * config parsing to free all default values.
1575 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001576 free(defproxy.check_req);
1577 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001578 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001579 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001580 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001581 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001582 free(defproxy.capture_name);
1583 free(defproxy.monitor_uri);
1584 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001585 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001586 free(defproxy.fwdfor_hdr_name);
1587 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001588 free(defproxy.orgto_hdr_name);
1589 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05001590 free(defproxy.server_id_hdr_name);
1591 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02001592 free(defproxy.expect_str);
1593 if (defproxy.expect_regex) regfree(defproxy.expect_regex);
Willy Tarreau0f772532006-12-23 20:51:41 +01001594
Willy Tarreaua534fea2008-08-03 12:19:50 +02001595 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001596 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001597
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 /* we cannot free uri_auth because it might already be used */
1599 init_default_instance();
1600 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001601 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 }
1604 else if (curproxy == NULL) {
1605 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001606 err_code |= ERR_ALERT | ERR_FATAL;
1607 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608 }
1609
Willy Tarreau977b8e42006-12-29 14:19:17 +01001610
1611 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001613 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001614 int cur_arg;
1615
Willy Tarreaubaaee002006-06-26 02:48:02 +02001616 if (curproxy == &defproxy) {
1617 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001618 err_code |= ERR_ALERT | ERR_FATAL;
1619 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001621 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001622 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623
Emeric Bruned760922010-10-22 17:59:25 +02001624 if ( *(args[1]) != '/' && strchr(args[1], ':') == NULL) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01001625 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001627 err_code |= ERR_ALERT | ERR_FATAL;
1628 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001630
1631 last_listen = curproxy->listen;
Willy Tarreau8a956912010-10-15 14:27:08 +02001632
1633 /* NOTE: the following line might create several listeners if there
1634 * are comma-separated IPs or port ranges. So all further processing
1635 * will have to be applied to all listeners created after last_listen.
1636 */
Willy Tarreau2dff0c22011-03-04 15:43:13 +01001637 if (!str2listener(args[1], curproxy, file, linenum)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001638 err_code |= ERR_ALERT | ERR_FATAL;
1639 goto out;
1640 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001641
Willy Tarreau90a570f2009-10-04 20:54:54 +02001642 new_listen = curproxy->listen;
1643 while (new_listen != last_listen) {
1644 new_listen->conf.file = file;
1645 new_listen->conf.line = linenum;
1646 new_listen = new_listen->next;
Willy Tarreauc8b11092011-02-16 11:08:57 +01001647 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001648 }
1649
Emeric Bruned760922010-10-22 17:59:25 +02001650 /* Set default global rights and owner for unix bind */
1651 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1652 memcpy(&(curproxy->listen->perm.ux), &(global.unix_bind.ux), sizeof(global.unix_bind.ux));
1653 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001654 cur_arg = 2;
1655 while (*(args[cur_arg])) {
1656 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1657#ifdef SO_BINDTODEVICE
1658 struct listener *l;
1659
Emeric Bruned760922010-10-22 17:59:25 +02001660 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1661 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1662 file, linenum, args[0], args[cur_arg]);
1663 err_code |= ERR_ALERT | ERR_FATAL;
1664 goto out;
1665 }
1666
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001667 if (!*args[cur_arg + 1]) {
1668 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001670 err_code |= ERR_ALERT | ERR_FATAL;
1671 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001672 }
1673
1674 for (l = curproxy->listen; l != last_listen; l = l->next)
1675 l->interface = strdup(args[cur_arg + 1]);
1676
1677 global.last_checks |= LSTCHK_NETADM;
1678
1679 cur_arg += 2;
1680 continue;
1681#else
1682 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1683 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001686#endif
1687 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001688 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1689#ifdef TCP_MAXSEG
1690 struct listener *l;
1691 int mss;
1692
Emeric Bruned760922010-10-22 17:59:25 +02001693 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1694 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1695 file, linenum, args[0], args[cur_arg]);
1696 err_code |= ERR_ALERT | ERR_FATAL;
1697 goto out;
1698 }
1699
Willy Tarreaube1b9182009-06-14 18:48:19 +02001700 if (!*args[cur_arg + 1]) {
1701 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1702 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001703 err_code |= ERR_ALERT | ERR_FATAL;
1704 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001705 }
1706
Willy Tarreau48a7e722010-12-24 15:26:39 +01001707 mss = atoi(args[cur_arg + 1]);
1708 if (!mss || abs(mss) > 65535) {
1709 Alert("parsing [%s:%d]: %s expects an MSS with and absolute value between 1 and 65535.\n",
Willy Tarreaube1b9182009-06-14 18:48:19 +02001710 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001711 err_code |= ERR_ALERT | ERR_FATAL;
1712 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001713 }
1714
1715 for (l = curproxy->listen; l != last_listen; l = l->next)
1716 l->maxseg = mss;
1717
1718 cur_arg += 2;
1719 continue;
1720#else
1721 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1722 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001723 err_code |= ERR_ALERT | ERR_FATAL;
1724 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001725#endif
1726 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001727
1728 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1729#ifdef TCP_DEFER_ACCEPT
1730 struct listener *l;
1731
1732 for (l = curproxy->listen; l != last_listen; l = l->next)
1733 l->options |= LI_O_DEF_ACCEPT;
1734
1735 cur_arg ++;
1736 continue;
1737#else
1738 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1739 file, linenum, args[0], args[cur_arg]);
1740 err_code |= ERR_ALERT | ERR_FATAL;
1741 goto out;
1742#endif
1743 }
1744
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001745 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001746#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001747 struct listener *l;
1748
Emeric Bruned760922010-10-22 17:59:25 +02001749 if (curproxy->listen->addr.ss_family == AF_UNIX) {
1750 Alert("parsing [%s:%d] : '%s' : '%s' option not supported on unix sockets.\n",
1751 file, linenum, args[0], args[cur_arg]);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 goto out;
1754 }
1755
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001756 for (l = curproxy->listen; l != last_listen; l = l->next)
1757 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001758
1759 cur_arg ++;
1760 continue;
1761#else
1762 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1763 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001766#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001767 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001768
Willy Tarreau8a956912010-10-15 14:27:08 +02001769 if (!strcmp(args[cur_arg], "accept-proxy")) { /* expect a 'PROXY' line first */
1770 struct listener *l;
1771
1772 for (l = curproxy->listen; l != last_listen; l = l->next)
1773 l->options |= LI_O_ACC_PROXY;
1774
1775 cur_arg ++;
1776 continue;
1777 }
1778
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001779 if (!strcmp(args[cur_arg], "name")) {
1780 struct listener *l;
1781
1782 for (l = curproxy->listen; l != last_listen; l = l->next)
1783 l->name = strdup(args[cur_arg + 1]);
1784
1785 cur_arg += 2;
1786 continue;
1787 }
1788
1789 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001790 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001791 struct listener *l;
1792
1793 if (curproxy->listen->next != last_listen) {
1794 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1795 file, linenum, args[cur_arg]);
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
1798 }
1799
1800 if (!*args[cur_arg + 1]) {
1801 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1802 file, linenum, args[cur_arg]);
1803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806
1807 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001808 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001809
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001810 if (curproxy->listen->luid <= 0) {
1811 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001812 file, linenum);
1813 err_code |= ERR_ALERT | ERR_FATAL;
1814 goto out;
1815 }
1816
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001817 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1818 if (node) {
1819 l = container_of(node, struct listener, conf.id);
1820 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1821 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1822 err_code |= ERR_ALERT | ERR_FATAL;
1823 goto out;
1824 }
1825 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1826
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001827 cur_arg += 2;
1828 continue;
1829 }
1830
Emeric Bruned760922010-10-22 17:59:25 +02001831 if (!strcmp(args[cur_arg], "mode")) {
1832
1833 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1834 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1835 file, linenum, args[0], args[cur_arg]);
1836 err_code |= ERR_ALERT | ERR_FATAL;
1837 goto out;
1838 }
1839
1840 curproxy->listen->perm.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1841
1842 cur_arg += 2;
1843 continue;
1844 }
1845
1846 if (!strcmp(args[cur_arg], "uid")) {
1847
1848 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1849 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1850 file, linenum, args[0], args[cur_arg]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854
1855 curproxy->listen->perm.ux.uid = atol(args[cur_arg + 1 ]);
1856 cur_arg += 2;
1857 continue;
1858 }
1859
1860 if (!strcmp(args[cur_arg], "gid")) {
1861
1862 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1863 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1864 file, linenum, args[0], args[cur_arg]);
1865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
1867 }
1868
1869 curproxy->listen->perm.ux.gid = atol(args[cur_arg + 1 ]);
1870 cur_arg += 2;
1871 continue;
1872 }
1873
1874 if (!strcmp(args[cur_arg], "user")) {
1875 struct passwd *user;
1876
1877 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1878 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1879 file, linenum, args[0], args[cur_arg]);
1880 err_code |= ERR_ALERT | ERR_FATAL;
1881 goto out;
1882 }
1883 user = getpwnam(args[cur_arg + 1]);
1884 if (!user) {
1885 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1886 file, linenum, args[0], args[cur_arg + 1 ]);
1887 err_code |= ERR_ALERT | ERR_FATAL;
1888 goto out;
1889 }
1890
1891 curproxy->listen->perm.ux.uid = user->pw_uid;
1892 cur_arg += 2;
1893 continue;
1894 }
1895
1896 if (!strcmp(args[cur_arg], "group")) {
1897 struct group *group;
1898
1899 if (curproxy->listen->addr.ss_family != AF_UNIX) {
1900 Alert("parsing [%s:%d] : '%s' : '%s' option only supported on unix sockets.\n",
1901 file, linenum, args[0], args[cur_arg]);
1902 err_code |= ERR_ALERT | ERR_FATAL;
1903 goto out;
1904 }
1905 group = getgrnam(args[cur_arg + 1]);
1906 if (!group) {
1907 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1908 file, linenum, args[0], args[cur_arg + 1 ]);
1909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
1911 }
1912
1913 curproxy->listen->perm.ux.gid = group->gr_gid;
1914 cur_arg += 2;
1915 continue;
1916 }
1917
Willy Tarreaub48f9582011-09-05 01:17:06 +02001918 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'accept-proxy', 'defer-accept', 'name', 'id', 'mss', 'mode', 'uid', 'gid', 'user', 'group' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001919 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001920 err_code |= ERR_ALERT | ERR_FATAL;
1921 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001922 }
Willy Tarreau93893792009-07-23 13:19:11 +02001923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924 }
1925 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1926 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1927 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1928 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
1930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001933 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001934
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 /* flush useless bits */
1936 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001937 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001939 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001940 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001942
Willy Tarreau1c47f852006-07-09 08:22:27 +02001943 if (!*args[1]) {
1944 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1945 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001946 err_code |= ERR_ALERT | ERR_FATAL;
1947 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001948 }
1949
Willy Tarreaua534fea2008-08-03 12:19:50 +02001950 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001951 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001952 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001953 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001954 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1955
Willy Tarreau93893792009-07-23 13:19:11 +02001956 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1959 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1960 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1961 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1962 else {
1963 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001964 err_code |= ERR_ALERT | ERR_FATAL;
1965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966 }
1967 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001968 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001969 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001970
1971 if (curproxy == &defproxy) {
1972 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001974 err_code |= ERR_ALERT | ERR_FATAL;
1975 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001976 }
1977
1978 if (!*args[1]) {
1979 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1980 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001983 }
1984
1985 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001986 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001987
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001988 if (curproxy->uuid <= 0) {
1989 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001990 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001991 err_code |= ERR_ALERT | ERR_FATAL;
1992 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001993 }
1994
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001995 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1996 if (node) {
1997 struct proxy *target = container_of(node, struct proxy, conf.id);
1998 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1999 file, linenum, proxy_type_str(curproxy), curproxy->id,
2000 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2001 err_code |= ERR_ALERT | ERR_FATAL;
2002 goto out;
2003 }
2004 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002005 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002006 else if (!strcmp(args[0], "description")) {
2007 int i, len=0;
2008 char *d;
2009
Cyril Bonté99ed3272010-01-24 23:29:44 +01002010 if (curproxy == &defproxy) {
2011 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2012 file, linenum, args[0]);
2013 err_code |= ERR_ALERT | ERR_FATAL;
2014 goto out;
2015 }
2016
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002017 if (!*args[1]) {
2018 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2019 file, linenum, args[0]);
2020 return -1;
2021 }
2022
2023 for(i=1; *args[i]; i++)
2024 len += strlen(args[i])+1;
2025
2026 d = (char *)calloc(1, len);
2027 curproxy->desc = d;
2028
2029 d += sprintf(d, "%s", args[1]);
2030 for(i=2; *args[i]; i++)
2031 d += sprintf(d, " %s", args[i]);
2032
2033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002034 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2035 curproxy->state = PR_STSTOPPED;
2036 }
2037 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2038 curproxy->state = PR_STNEW;
2039 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002040 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2041 int cur_arg = 1;
2042 unsigned int set = 0;
2043
2044 while (*args[cur_arg]) {
2045 int u;
2046 if (strcmp(args[cur_arg], "all") == 0) {
2047 set = 0;
2048 break;
2049 }
2050 else if (strcmp(args[cur_arg], "odd") == 0) {
2051 set |= 0x55555555;
2052 }
2053 else if (strcmp(args[cur_arg], "even") == 0) {
2054 set |= 0xAAAAAAAA;
2055 }
2056 else {
2057 u = str2uic(args[cur_arg]);
2058 if (u < 1 || u > 32) {
2059 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
2060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002061 err_code |= ERR_ALERT | ERR_FATAL;
2062 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002063 }
2064 if (u > global.nbproc) {
2065 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
2066 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002067 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002068 }
2069 set |= 1 << (u - 1);
2070 }
2071 cur_arg++;
2072 }
2073 curproxy->bind_proc = set;
2074 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002075 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002076 if (curproxy == &defproxy) {
2077 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002078 err_code |= ERR_ALERT | ERR_FATAL;
2079 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002080 }
2081
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002082 err = invalid_char(args[1]);
2083 if (err) {
2084 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2085 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002086 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002087 }
2088
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002089 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
2090 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
2091 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002092 err_code |= ERR_ALERT | ERR_FATAL;
2093 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002094 }
2095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2097 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098
Willy Tarreau977b8e42006-12-29 14:19:17 +01002099 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002100 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002101
Willy Tarreaubaaee002006-06-26 02:48:02 +02002102 if (*(args[1]) == 0) {
2103 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2104 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
2106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002108
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002109 curproxy->options &= ~PR_O_COOK_ANY;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002110 curproxy->options2 &= ~PR_O2_COOK_PSV;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002111 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002112 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002113 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 curproxy->cookie_name = strdup(args[1]);
2115 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002116
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 cur_arg = 2;
2118 while (*(args[cur_arg])) {
2119 if (!strcmp(args[cur_arg], "rewrite")) {
2120 curproxy->options |= PR_O_COOK_RW;
2121 }
2122 else if (!strcmp(args[cur_arg], "indirect")) {
2123 curproxy->options |= PR_O_COOK_IND;
2124 }
2125 else if (!strcmp(args[cur_arg], "insert")) {
2126 curproxy->options |= PR_O_COOK_INS;
2127 }
2128 else if (!strcmp(args[cur_arg], "nocache")) {
2129 curproxy->options |= PR_O_COOK_NOC;
2130 }
2131 else if (!strcmp(args[cur_arg], "postonly")) {
2132 curproxy->options |= PR_O_COOK_POST;
2133 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002134 else if (!strcmp(args[cur_arg], "preserve")) {
2135 curproxy->options2 |= PR_O2_COOK_PSV;
2136 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 else if (!strcmp(args[cur_arg], "prefix")) {
2138 curproxy->options |= PR_O_COOK_PFX;
2139 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002140 else if (!strcmp(args[cur_arg], "domain")) {
2141 if (!*args[cur_arg + 1]) {
2142 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2143 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002144 err_code |= ERR_ALERT | ERR_FATAL;
2145 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002146 }
2147
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002148 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002149 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002150 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2151 " dots nor does not start with a dot."
2152 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002153 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002154 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002155 }
2156
2157 err = invalid_domainchar(args[cur_arg + 1]);
2158 if (err) {
2159 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2160 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002161 err_code |= ERR_ALERT | ERR_FATAL;
2162 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002163 }
2164
Willy Tarreau68a897b2009-12-03 23:28:34 +01002165 if (!curproxy->cookie_domain) {
2166 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2167 } else {
2168 /* one domain was already specified, add another one by
2169 * building the string which will be returned along with
2170 * the cookie.
2171 */
2172 char *new_ptr;
2173 int new_len = strlen(curproxy->cookie_domain) +
2174 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2175 new_ptr = malloc(new_len);
2176 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2177 free(curproxy->cookie_domain);
2178 curproxy->cookie_domain = new_ptr;
2179 }
Willy Tarreau31936852010-10-06 16:59:56 +02002180 cur_arg++;
2181 }
2182 else if (!strcmp(args[cur_arg], "maxidle")) {
2183 unsigned int maxidle;
2184 const char *res;
2185
2186 if (!*args[cur_arg + 1]) {
2187 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2188 file, linenum, args[cur_arg]);
2189 err_code |= ERR_ALERT | ERR_FATAL;
2190 goto out;
2191 }
2192
2193 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2194 if (res) {
2195 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2196 file, linenum, *res, args[cur_arg]);
2197 err_code |= ERR_ALERT | ERR_FATAL;
2198 goto out;
2199 }
2200 curproxy->cookie_maxidle = maxidle;
2201 cur_arg++;
2202 }
2203 else if (!strcmp(args[cur_arg], "maxlife")) {
2204 unsigned int maxlife;
2205 const char *res;
2206
2207 if (!*args[cur_arg + 1]) {
2208 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2209 file, linenum, args[cur_arg]);
2210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
2212 }
2213
2214 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2215 if (res) {
2216 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2217 file, linenum, *res, args[cur_arg]);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
2220 }
2221 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002222 cur_arg++;
2223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002224 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002225 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 +02002226 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002227 err_code |= ERR_ALERT | ERR_FATAL;
2228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002229 }
2230 cur_arg++;
2231 }
2232 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
2233 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2234 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002235 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002236 }
2237
2238 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
2239 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2240 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002241 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002243
2244 if ((curproxy->options2 & PR_O2_COOK_PSV) && !(curproxy->options & (PR_O_COOK_INS|PR_O_COOK_IND))) {
2245 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2246 file, linenum);
2247 err_code |= ERR_ALERT | ERR_FATAL;
2248 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002250 else if (!strcmp(args[0], "persist")) { /* persist */
2251 if (*(args[1]) == 0) {
2252 Alert("parsing [%s:%d] : missing persist method.\n",
2253 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002256 }
2257
2258 if (!strncmp(args[1], "rdp-cookie", 10)) {
2259 curproxy->options2 |= PR_O2_RDPC_PRST;
2260
Emeric Brunb982a3d2010-01-04 15:45:53 +01002261 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002262 const char *beg, *end;
2263
2264 beg = args[1] + 11;
2265 end = strchr(beg, ')');
2266
2267 if (!end || end == beg) {
2268 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2269 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002272 }
2273
2274 free(curproxy->rdp_cookie_name);
2275 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2276 curproxy->rdp_cookie_len = end-beg;
2277 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002278 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002279 free(curproxy->rdp_cookie_name);
2280 curproxy->rdp_cookie_name = strdup("msts");
2281 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2282 }
2283 else { /* syntax */
2284 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2285 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002288 }
2289 }
2290 else {
2291 Alert("parsing [%s:%d] : unknown persist method.\n",
2292 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002293 err_code |= ERR_ALERT | ERR_FATAL;
2294 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002295 }
2296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002297 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002298 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002300 if (curproxy == &defproxy) {
2301 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
2304 }
2305
Willy Tarreau977b8e42006-12-29 14:19:17 +01002306 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002307 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002308
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002310 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002314 }
2315 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002316 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317 curproxy->appsession_name = strdup(args[1]);
2318 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2319 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002320 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2321 if (err) {
2322 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2323 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002326 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002327 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002328
Willy Tarreau51041c72007-09-09 21:56:53 +02002329 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2330 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002331 err_code |= ERR_ALERT | ERR_ABORT;
2332 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002334
2335 cur_arg = 6;
2336 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002337 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2338 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002339 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002340 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002341 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002342 } else if (!strcmp(args[cur_arg], "prefix")) {
2343 curproxy->options2 |= PR_O2_AS_PFX;
2344 } else if (!strcmp(args[cur_arg], "mode")) {
2345 if (!*args[cur_arg + 1]) {
2346 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2347 file, linenum, args[0], args[cur_arg]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351
2352 cur_arg++;
2353 if (!strcmp(args[cur_arg], "query-string")) {
2354 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2355 curproxy->options2 |= PR_O2_AS_M_QS;
2356 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2357 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2358 curproxy->options2 |= PR_O2_AS_M_PP;
2359 } else {
2360 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2361 err_code |= ERR_ALERT | ERR_FATAL;
2362 goto out;
2363 }
2364 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002365 cur_arg++;
2366 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002367 } /* Url App Session */
2368 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002369 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002371
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002373 if (curproxy == &defproxy) {
2374 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 if (*(args[4]) == 0) {
2380 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002382 err_code |= ERR_ALERT | ERR_FATAL;
2383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002385 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002386 curproxy->capture_name = strdup(args[2]);
2387 curproxy->capture_namelen = strlen(curproxy->capture_name);
2388 curproxy->capture_len = atol(args[4]);
2389 if (curproxy->capture_len >= CAPTURE_LEN) {
2390 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
2391 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02002392 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 curproxy->capture_len = CAPTURE_LEN - 1;
2394 }
2395 curproxy->to_log |= LW_COOKIE;
2396 }
2397 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2398 struct cap_hdr *hdr;
2399
2400 if (curproxy == &defproxy) {
2401 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 +02002402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 }
2405
2406 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2407 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2408 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411 }
2412
2413 hdr = calloc(sizeof(struct cap_hdr), 1);
2414 hdr->next = curproxy->req_cap;
2415 hdr->name = strdup(args[3]);
2416 hdr->namelen = strlen(args[3]);
2417 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002418 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419 hdr->index = curproxy->nb_req_cap++;
2420 curproxy->req_cap = hdr;
2421 curproxy->to_log |= LW_REQHDR;
2422 }
2423 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2424 struct cap_hdr *hdr;
2425
2426 if (curproxy == &defproxy) {
2427 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 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431
2432 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2433 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2434 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 }
2438 hdr = calloc(sizeof(struct cap_hdr), 1);
2439 hdr->next = curproxy->rsp_cap;
2440 hdr->name = strdup(args[3]);
2441 hdr->namelen = strlen(args[3]);
2442 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002443 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444 hdr->index = curproxy->nb_rsp_cap++;
2445 curproxy->rsp_cap = hdr;
2446 curproxy->to_log |= LW_RSPHDR;
2447 }
2448 else {
2449 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2450 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_ALERT | ERR_FATAL;
2452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 }
2454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002456 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 if (*(args[1]) == 0) {
2460 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2461 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002462 err_code |= ERR_ALERT | ERR_FATAL;
2463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002464 }
2465 curproxy->conn_retries = atol(args[1]);
2466 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002467 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002468 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002469
2470 if (curproxy == &defproxy) {
2471 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2472 err_code |= ERR_ALERT | ERR_FATAL;
2473 goto out;
2474 }
2475
Willy Tarreauff011f22011-01-06 17:51:27 +01002476 if (!LIST_ISEMPTY(&curproxy->http_req_rules) && !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002477 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
2478 file, linenum, args[0]);
2479 err_code |= ERR_WARN;
2480 }
2481
Willy Tarreauff011f22011-01-06 17:51:27 +01002482 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002483
Willy Tarreauff011f22011-01-06 17:51:27 +01002484 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002485 err_code |= ERR_ALERT | ERR_ABORT;
2486 goto out;
2487 }
2488
Willy Tarreauff011f22011-01-06 17:51:27 +01002489 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
2490 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002491 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002492 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2493 /* set the header name and length into the proxy structure */
2494 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2495 err_code |= ERR_WARN;
2496
2497 if (!*args[1]) {
2498 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2499 file, linenum, args[0]);
2500 err_code |= ERR_ALERT | ERR_FATAL;
2501 goto out;
2502 }
2503
2504 /* set the desired header name */
2505 free(curproxy->server_id_hdr_name);
2506 curproxy->server_id_hdr_name = strdup(args[1]);
2507 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2508 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002509 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002510 if (curproxy == &defproxy) {
2511 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002512 err_code |= ERR_ALERT | ERR_FATAL;
2513 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002514 }
2515
Willy Tarreauef6494c2010-01-28 17:12:36 +01002516 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002517 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2518 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002521 }
2522
Willy Tarreauef6494c2010-01-28 17:12:36 +01002523 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002524 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
2525 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002528 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002529
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002530 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02002531 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002532 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002533 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002534 struct redirect_rule *rule;
2535 int cur_arg;
2536 int type = REDIRECT_TYPE_NONE;
2537 int code = 302;
2538 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01002539 char *cookie = NULL;
2540 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01002541 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002542
Cyril Bonté99ed3272010-01-24 23:29:44 +01002543 if (curproxy == &defproxy) {
2544 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2545 err_code |= ERR_ALERT | ERR_FATAL;
2546 goto out;
2547 }
2548
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002549 cur_arg = 1;
2550 while (*(args[cur_arg])) {
2551 if (!strcmp(args[cur_arg], "location")) {
2552 if (!*args[cur_arg + 1]) {
2553 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2554 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_ALERT | ERR_FATAL;
2556 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002557 }
2558
2559 type = REDIRECT_TYPE_LOCATION;
2560 cur_arg++;
2561 destination = args[cur_arg];
2562 }
2563 else if (!strcmp(args[cur_arg], "prefix")) {
2564 if (!*args[cur_arg + 1]) {
2565 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2566 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002569 }
2570
2571 type = REDIRECT_TYPE_PREFIX;
2572 cur_arg++;
2573 destination = args[cur_arg];
2574 }
Willy Tarreau0140f252008-11-19 21:07:09 +01002575 else if (!strcmp(args[cur_arg], "set-cookie")) {
2576 if (!*args[cur_arg + 1]) {
2577 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2578 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002579 err_code |= ERR_ALERT | ERR_FATAL;
2580 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002581 }
2582
2583 cur_arg++;
2584 cookie = args[cur_arg];
2585 cookie_set = 1;
2586 }
2587 else if (!strcmp(args[cur_arg], "clear-cookie")) {
2588 if (!*args[cur_arg + 1]) {
2589 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2590 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002591 err_code |= ERR_ALERT | ERR_FATAL;
2592 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01002593 }
2594
2595 cur_arg++;
2596 cookie = args[cur_arg];
2597 cookie_set = 0;
2598 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002599 else if (!strcmp(args[cur_arg],"code")) {
2600 if (!*args[cur_arg + 1]) {
2601 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
2602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002605 }
2606 cur_arg++;
2607 code = atol(args[cur_arg]);
2608 if (code < 301 || code > 303) {
2609 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
2610 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02002611 err_code |= ERR_ALERT | ERR_FATAL;
2612 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002613 }
2614 }
Willy Tarreau79da4692008-11-19 20:03:04 +01002615 else if (!strcmp(args[cur_arg],"drop-query")) {
2616 flags |= REDIRECT_FLAG_DROP_QS;
2617 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002618 else if (!strcmp(args[cur_arg],"append-slash")) {
2619 flags |= REDIRECT_FLAG_APPEND_SLASH;
2620 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01002621 else if (strcmp(args[cur_arg], "if") == 0 ||
2622 strcmp(args[cur_arg], "unless") == 0) {
2623 cond = build_acl_cond(file, linenum, curproxy, (const char **)args + cur_arg);
2624 if (!cond) {
2625 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
2626 file, linenum, args[0]);
2627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
2629 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002630 break;
2631 }
2632 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01002633 Alert("parsing [%s:%d] : '%s' expects 'code', 'prefix', 'location', 'set-cookie', 'clear-cookie', 'drop-query' or 'append-slash' (was '%s').\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002634 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002637 }
2638 cur_arg++;
2639 }
2640
2641 if (type == REDIRECT_TYPE_NONE) {
2642 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
2643 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002646 }
2647
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002648 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
2649 rule->cond = cond;
2650 rule->rdr_str = strdup(destination);
2651 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01002652 if (cookie) {
2653 /* depending on cookie_set, either we want to set the cookie, or to clear it.
William Turnerd9865262010-03-01 13:30:34 -05002654 * a clear consists in appending "; path=/; Max-Age=0;" at the end.
Willy Tarreau0140f252008-11-19 21:07:09 +01002655 */
2656 rule->cookie_len = strlen(cookie);
William Turnerd9865262010-03-01 13:30:34 -05002657 if (cookie_set) {
2658 rule->cookie_str = malloc(rule->cookie_len + 10);
2659 memcpy(rule->cookie_str, cookie, rule->cookie_len);
2660 memcpy(rule->cookie_str + rule->cookie_len, "; path=/;", 10);
2661 rule->cookie_len += 9;
2662 } else {
2663 rule->cookie_str = malloc(rule->cookie_len + 21);
Willy Tarreau0140f252008-11-19 21:07:09 +01002664 memcpy(rule->cookie_str, cookie, rule->cookie_len);
William Turnerd9865262010-03-01 13:30:34 -05002665 memcpy(rule->cookie_str + rule->cookie_len, "; path=/; Max-Age=0;", 21);
2666 rule->cookie_len += 20;
Willy Tarreau0140f252008-11-19 21:07:09 +01002667 }
2668 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002669 rule->type = type;
2670 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01002671 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002672 LIST_INIT(&rule->list);
2673 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau9d9ed012011-02-23 15:24:42 +01002674 err_code |= warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
2675 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002676 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01002677 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002678 struct switching_rule *rule;
2679
Willy Tarreaub099aca2008-10-12 17:26:37 +02002680 if (curproxy == &defproxy) {
2681 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002682 err_code |= ERR_ALERT | ERR_FATAL;
2683 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002684 }
2685
Willy Tarreau55ea7572007-06-17 19:56:27 +02002686 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002687 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002688
2689 if (*(args[1]) == 0) {
2690 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002693 }
2694
Willy Tarreauef6494c2010-01-28 17:12:36 +01002695 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02002696 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2697 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002698 err_code |= ERR_ALERT | ERR_FATAL;
2699 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002700 }
2701
Willy Tarreauef6494c2010-01-28 17:12:36 +01002702 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002703 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002704 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002705 err_code |= ERR_ALERT | ERR_FATAL;
2706 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002707 }
2708
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002709 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreaua9802632008-07-25 19:13:19 +02002710
Willy Tarreau55ea7572007-06-17 19:56:27 +02002711 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2712 rule->cond = cond;
2713 rule->be.name = strdup(args[1]);
2714 LIST_INIT(&rule->list);
2715 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2716 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002717 else if (strcmp(args[0], "use-server") == 0) {
2718 struct server_rule *rule;
2719
2720 if (curproxy == &defproxy) {
2721 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2722 err_code |= ERR_ALERT | ERR_FATAL;
2723 goto out;
2724 }
2725
2726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2727 err_code |= ERR_WARN;
2728
2729 if (*(args[1]) == 0) {
2730 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
2731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
2733 }
2734
2735 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2736 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2737 file, linenum, args[0]);
2738 err_code |= ERR_ALERT | ERR_FATAL;
2739 goto out;
2740 }
2741
2742 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
2743 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
2744 file, linenum);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748
2749 err_code |= warnif_cond_requires_resp(cond, file, linenum);
2750
2751 rule = (struct server_rule *)calloc(1, sizeof(*rule));
2752 rule->cond = cond;
2753 rule->srv.name = strdup(args[1]);
2754 LIST_INIT(&rule->list);
2755 LIST_ADDQ(&curproxy->server_rules, &rule->list);
2756 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
2757 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002758 else if ((!strcmp(args[0], "force-persist")) ||
2759 (!strcmp(args[0], "ignore-persist"))) {
2760 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01002761
2762 if (curproxy == &defproxy) {
2763 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
2766 }
2767
2768 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2769 err_code |= ERR_WARN;
2770
Willy Tarreauef6494c2010-01-28 17:12:36 +01002771 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01002772 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2773 file, linenum, args[0]);
2774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
2776 }
2777
Willy Tarreauef6494c2010-01-28 17:12:36 +01002778 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1)) == NULL) {
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002779 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule.\n",
2780 file, linenum, args[0]);
Willy Tarreau4de91492010-01-22 19:10:05 +01002781 err_code |= ERR_ALERT | ERR_FATAL;
2782 goto out;
2783 }
2784
Willy Tarreauf1e98b82010-01-28 17:59:39 +01002785 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01002786
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002787 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01002788 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002789 if (!strcmp(args[0], "force-persist")) {
2790 rule->type = PERSIST_TYPE_FORCE;
2791 } else {
2792 rule->type = PERSIST_TYPE_IGNORE;
2793 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002794 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02002795 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01002796 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002797 else if (!strcmp(args[0], "stick-table")) {
2798 int myidx = 1;
2799
Emeric Brun32da3c42010-09-23 18:39:19 +02002800 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002801 curproxy->table.type = (unsigned int)-1;
2802 while (*args[myidx]) {
2803 const char *err;
2804
2805 if (strcmp(args[myidx], "size") == 0) {
2806 myidx++;
2807 if (!*(args[myidx])) {
2808 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2809 file, linenum, args[myidx-1]);
2810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
2812 }
2813 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2814 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2815 file, linenum, *err, args[myidx-1]);
2816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002819 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002820 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002821 else if (strcmp(args[myidx], "peers") == 0) {
2822 myidx++;
2823 if (!*(args[myidx])) {
2824 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2825 file, linenum, args[myidx-1]);
2826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
2828 }
2829 curproxy->table.peers.name = strdup(args[myidx++]);
2830 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002831 else if (strcmp(args[myidx], "expire") == 0) {
2832 myidx++;
2833 if (!*(args[myidx])) {
2834 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2835 file, linenum, args[myidx-1]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2840 if (err) {
2841 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2842 file, linenum, *err, args[myidx-1]);
2843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
2845 }
2846 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01002847 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002848 }
2849 else if (strcmp(args[myidx], "nopurge") == 0) {
2850 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01002851 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002852 }
2853 else if (strcmp(args[myidx], "type") == 0) {
2854 myidx++;
2855 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2856 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2857 file, linenum, args[myidx]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002861 /* myidx already points to next arg */
2862 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002863 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02002864 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02002865 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02002866
2867 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002868 nw = args[myidx];
2869 while (*nw) {
2870 /* the "store" keyword supports a comma-separated list */
2871 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02002872 sa = NULL; /* store arg */
2873 while (*nw && *nw != ',') {
2874 if (*nw == '(') {
2875 *nw = 0;
2876 sa = ++nw;
2877 while (*nw != ')') {
2878 if (!*nw) {
2879 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
2880 file, linenum, args[0], cw);
2881 err_code |= ERR_ALERT | ERR_FATAL;
2882 goto out;
2883 }
2884 nw++;
2885 }
2886 *nw = '\0';
2887 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002888 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02002889 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002890 if (*nw)
2891 *nw++ = '\0';
2892 type = stktable_get_data_type(cw);
2893 if (type < 0) {
2894 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
2895 file, linenum, args[0], cw);
2896 err_code |= ERR_ALERT | ERR_FATAL;
2897 goto out;
2898 }
Willy Tarreauac782882010-06-20 10:41:54 +02002899
2900 err = stktable_alloc_data_type(&curproxy->table, type, sa);
2901 switch (err) {
2902 case PE_NONE: break;
2903 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002904 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
2905 file, linenum, args[0], cw);
2906 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02002907 break;
2908
2909 case PE_ARG_MISSING:
2910 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
2911 file, linenum, args[0], cw);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914
2915 case PE_ARG_NOT_USED:
2916 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
2917 file, linenum, args[0], cw);
2918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920
2921 default:
2922 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
2923 file, linenum, args[0], cw);
2924 err_code |= ERR_ALERT | ERR_FATAL;
2925 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02002926 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02002927 }
2928 myidx++;
2929 }
Willy Tarreau0c559312010-01-26 18:36:26 +01002930 else {
2931 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
2932 file, linenum, args[myidx]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01002935 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002936 }
2937
2938 if (!curproxy->table.size) {
2939 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2940 file, linenum);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
2944
2945 if (curproxy->table.type == (unsigned int)-1) {
2946 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2947 file, linenum);
2948 err_code |= ERR_ALERT | ERR_FATAL;
2949 goto out;
2950 }
2951 }
2952 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01002953 struct sticking_rule *rule;
2954 struct pattern_expr *expr;
2955 int myidx = 0;
2956 const char *name = NULL;
2957 int flags;
2958
2959 if (curproxy == &defproxy) {
2960 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964
2965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2966 err_code |= ERR_WARN;
2967 goto out;
2968 }
2969
2970 myidx++;
2971 if ((strcmp(args[myidx], "store") == 0) ||
2972 (strcmp(args[myidx], "store-request") == 0)) {
2973 myidx++;
2974 flags = STK_IS_STORE;
2975 }
2976 else if (strcmp(args[myidx], "store-response") == 0) {
2977 myidx++;
2978 flags = STK_IS_STORE | STK_ON_RSP;
2979 }
2980 else if (strcmp(args[myidx], "match") == 0) {
2981 myidx++;
2982 flags = STK_IS_MATCH;
2983 }
2984 else if (strcmp(args[myidx], "on") == 0) {
2985 myidx++;
2986 flags = STK_IS_MATCH | STK_IS_STORE;
2987 }
2988 else {
2989 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2990 err_code |= ERR_ALERT | ERR_FATAL;
2991 goto out;
2992 }
2993
2994 if (*(args[myidx]) == 0) {
2995 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
2998 }
2999
Emeric Brun485479d2010-09-23 18:02:19 +02003000 expr = pattern_parse_expr(args, &myidx, trash, sizeof(trash));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003001 if (!expr) {
Emeric Brun485479d2010-09-23 18:02:19 +02003002 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], trash);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
3005 }
3006
3007 if (flags & STK_ON_RSP) {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003008 if (!(expr->fetch->cap & SMP_CAP_RES)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003009 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
3010 file, linenum, args[0], expr->fetch->kw);
3011 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003012 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003013 goto out;
3014 }
3015 } else {
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02003016 if (!(expr->fetch->cap & SMP_CAP_REQ)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003017 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
3018 file, linenum, args[0], expr->fetch->kw);
3019 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003020 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003021 goto out;
3022 }
3023 }
3024
3025 if (strcmp(args[myidx], "table") == 0) {
3026 myidx++;
3027 name = args[myidx++];
3028 }
3029
Willy Tarreauef6494c2010-01-28 17:12:36 +01003030 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
3031 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx)) == NULL) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003032 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
3033 file, linenum, args[0]);
3034 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003035 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003036 goto out;
3037 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003038 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003039 else if (*(args[myidx])) {
3040 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3041 file, linenum, args[0], args[myidx]);
3042 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003043 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003044 goto out;
3045 }
Emeric Brun97679e72010-09-23 17:56:44 +02003046 if (flags & STK_ON_RSP)
3047 err_code |= warnif_cond_requires_req(cond, file, linenum);
3048 else
3049 err_code |= warnif_cond_requires_resp(cond, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003050
Emeric Brunb982a3d2010-01-04 15:45:53 +01003051 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3052 rule->cond = cond;
3053 rule->expr = expr;
3054 rule->flags = flags;
3055 rule->table.name = name ? strdup(name) : NULL;
3056 LIST_INIT(&rule->list);
3057 if (flags & STK_ON_RSP)
3058 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3059 else
3060 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3061 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003063 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003065
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3067 curproxy->uri_auth = NULL; /* we must detach from the default config */
3068
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003069 if (!*args[1]) {
3070 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003071 } else if (!strcmp(args[1], "admin")) {
3072 struct stats_admin_rule *rule;
3073
3074 if (curproxy == &defproxy) {
3075 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
3078 }
3079
3080 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3081 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3082 err_code |= ERR_ALERT | ERR_ABORT;
3083 goto out;
3084 }
3085
3086 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3087 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3088 file, linenum, args[0], args[1]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
3093 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule.\n",
3094 file, linenum, args[0], args[1]);
3095 err_code |= ERR_ALERT | ERR_FATAL;
3096 goto out;
3097 }
3098
3099 err_code |= warnif_cond_requires_resp(cond, file, linenum);
3100
3101 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3102 rule->cond = cond;
3103 LIST_INIT(&rule->list);
3104 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 } else if (!strcmp(args[1], "uri")) {
3106 if (*(args[2]) == 0) {
3107 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3111 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_ALERT | ERR_ABORT;
3113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 }
3115 } else if (!strcmp(args[1], "realm")) {
3116 if (*(args[2]) == 0) {
3117 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3121 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_ALERT | ERR_ABORT;
3123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003125 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003126 unsigned interval;
3127
3128 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3129 if (err) {
3130 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3131 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003134 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3135 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003136 err_code |= ERR_ALERT | ERR_ABORT;
3137 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003138 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003139 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003140 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003141
3142 if (curproxy == &defproxy) {
3143 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
3146 }
3147
3148 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3149 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3150 err_code |= ERR_ALERT | ERR_ABORT;
3151 goto out;
3152 }
3153
Willy Tarreauff011f22011-01-06 17:51:27 +01003154 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3155 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003156 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3157 file, linenum, args[0]);
3158 err_code |= ERR_WARN;
3159 }
3160
Willy Tarreauff011f22011-01-06 17:51:27 +01003161 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003162
Willy Tarreauff011f22011-01-06 17:51:27 +01003163 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003164 err_code |= ERR_ALERT | ERR_ABORT;
3165 goto out;
3166 }
3167
Willy Tarreauff011f22011-01-06 17:51:27 +01003168 err_code |= warnif_cond_requires_resp(rule->cond, file, linenum);
3169 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003170
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 } else if (!strcmp(args[1], "auth")) {
3172 if (*(args[2]) == 0) {
3173 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3177 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_ABORT;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181 } else if (!strcmp(args[1], "scope")) {
3182 if (*(args[2]) == 0) {
3183 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3187 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_ABORT;
3189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 }
3191 } else if (!strcmp(args[1], "enable")) {
3192 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3193 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_ABORT;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003197 } else if (!strcmp(args[1], "hide-version")) {
3198 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3199 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_ALERT | ERR_ABORT;
3201 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003202 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003203 } else if (!strcmp(args[1], "show-legends")) {
3204 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3205 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3206 err_code |= ERR_ALERT | ERR_ABORT;
3207 goto out;
3208 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003209 } else if (!strcmp(args[1], "show-node")) {
3210
3211 if (*args[2]) {
3212 int i;
3213 char c;
3214
3215 for (i=0; args[2][i]; i++) {
3216 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003217 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3218 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003219 break;
3220 }
3221
3222 if (!i || args[2][i]) {
3223 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3224 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3225 file, linenum, args[0], args[1]);
3226 err_code |= ERR_ALERT | ERR_FATAL;
3227 goto out;
3228 }
3229 }
3230
3231 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3232 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
3235 }
3236 } else if (!strcmp(args[1], "show-desc")) {
3237 char *desc = NULL;
3238
3239 if (*args[2]) {
3240 int i, len=0;
3241 char *d;
3242
3243 for(i=2; *args[i]; i++)
3244 len += strlen(args[i])+1;
3245
3246 desc = d = (char *)calloc(1, len);
3247
3248 d += sprintf(d, "%s", args[2]);
3249 for(i=3; *args[i]; i++)
3250 d += sprintf(d, " %s", args[i]);
3251 }
3252
3253 if (!*args[2] && !global.desc)
3254 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3255 file, linenum, args[1]);
3256 else {
3257 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3258 free(desc);
3259 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3260 err_code |= ERR_ALERT | ERR_ABORT;
3261 goto out;
3262 }
3263 free(desc);
3264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003266stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003267 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 +01003268 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 }
3272 }
3273 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003274 int optnum;
3275
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003276 if (*(args[1]) == '\0') {
3277 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003281 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003282
3283 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3284 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003285 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3286 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3287 file, linenum, cfg_opts[optnum].name);
3288 err_code |= ERR_ALERT | ERR_FATAL;
3289 goto out;
3290 }
Willy Tarreau93893792009-07-23 13:19:11 +02003291 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3292 err_code |= ERR_WARN;
3293 goto out;
3294 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003295
Willy Tarreau3842f002009-06-14 11:39:52 +02003296 curproxy->no_options &= ~cfg_opts[optnum].val;
3297 curproxy->options &= ~cfg_opts[optnum].val;
3298
3299 switch (kwm) {
3300 case KWM_STD:
3301 curproxy->options |= cfg_opts[optnum].val;
3302 break;
3303 case KWM_NO:
3304 curproxy->no_options |= cfg_opts[optnum].val;
3305 break;
3306 case KWM_DEF: /* already cleared */
3307 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003308 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003309
Willy Tarreau93893792009-07-23 13:19:11 +02003310 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003311 }
3312 }
3313
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003314 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3315 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003316 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3317 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3318 file, linenum, cfg_opts2[optnum].name);
3319 err_code |= ERR_ALERT | ERR_FATAL;
3320 goto out;
3321 }
Willy Tarreau93893792009-07-23 13:19:11 +02003322 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3323 err_code |= ERR_WARN;
3324 goto out;
3325 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003326
Willy Tarreau3842f002009-06-14 11:39:52 +02003327 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3328 curproxy->options2 &= ~cfg_opts2[optnum].val;
3329
3330 switch (kwm) {
3331 case KWM_STD:
3332 curproxy->options2 |= cfg_opts2[optnum].val;
3333 break;
3334 case KWM_NO:
3335 curproxy->no_options2 |= cfg_opts2[optnum].val;
3336 break;
3337 case KWM_DEF: /* already cleared */
3338 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003339 }
Willy Tarreau93893792009-07-23 13:19:11 +02003340 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003341 }
3342 }
3343
Willy Tarreau3842f002009-06-14 11:39:52 +02003344 if (kwm != KWM_STD) {
3345 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003346 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003349 }
3350
Emeric Brun3a058f32009-06-30 18:26:00 +02003351 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003352 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003354 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003355 if (*(args[2]) != '\0') {
3356 if (!strcmp(args[2], "clf")) {
3357 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003358 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003359 } else {
3360 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003363 }
3364 }
William Lallemand1d705562012-03-12 12:46:41 +01003365 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
Emeric Brun3a058f32009-06-30 18:26:00 +02003366 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003367 else if (!strcmp(args[1], "tcplog")) {
3368 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 /* generate a detailed TCP log */
William Lallemandbddd4fd2012-02-27 11:23:10 +01003370 logformat = default_tcp_log_format;
William Lallemand1d705562012-03-12 12:46:41 +01003371 parse_logformat_string(logformat, curproxy, &curproxy->logformat, curproxy->mode);
William Lallemandbddd4fd2012-02-27 11:23:10 +01003372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 else if (!strcmp(args[1], "tcpka")) {
3374 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003375 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003377
3378 if (curproxy->cap & PR_CAP_FE)
3379 curproxy->options |= PR_O_TCP_CLI_KA;
3380 if (curproxy->cap & PR_CAP_BE)
3381 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 }
3383 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003384 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_WARN;
3386
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003388 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003389 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003390 curproxy->options2 &= ~PR_O2_CHK_ANY;
3391 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 if (!*args[2]) { /* no argument */
3393 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3394 curproxy->check_len = strlen(DEF_CHECK_REQ);
3395 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003396 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 curproxy->check_req = (char *)malloc(reqlen);
3398 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003399 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003401 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 if (*args[4])
3403 reqlen += strlen(args[4]);
3404 else
3405 reqlen += strlen("HTTP/1.0");
3406
3407 curproxy->check_req = (char *)malloc(reqlen);
3408 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003409 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003411 }
3412 else if (!strcmp(args[1], "ssl-hello-chk")) {
3413 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003414 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003415 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003416
Willy Tarreaua534fea2008-08-03 12:19:50 +02003417 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003418 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003419 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003420 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
Willy Tarreau23677902007-05-08 23:50:35 +02003422 else if (!strcmp(args[1], "smtpchk")) {
3423 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003424 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003425 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003426 curproxy->options2 &= ~PR_O2_CHK_ANY;
3427 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003428
3429 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3430 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3431 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3432 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3433 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3434 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3435 curproxy->check_req = (char *)malloc(reqlen);
3436 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3437 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3438 } else {
3439 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3440 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3441 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3442 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3443 }
3444 }
3445 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003446 else if (!strcmp(args[1], "pgsql-check")) {
3447 /* use PostgreSQL request to check servers' health */
3448 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3449 err_code |= ERR_WARN;
3450
3451 free(curproxy->check_req);
3452 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003453 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003454 curproxy->options2 |= PR_O2_PGSQL_CHK;
3455
3456 if (*(args[2])) {
3457 int cur_arg = 2;
3458
3459 while (*(args[cur_arg])) {
3460 if (strcmp(args[cur_arg], "user") == 0) {
3461 char * packet;
3462 uint32_t packet_len;
3463 uint32_t pv;
3464
3465 /* suboption header - needs additional argument for it */
3466 if (*(args[cur_arg+1]) == 0) {
3467 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3468 file, linenum, args[0], args[1], args[cur_arg]);
3469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
3471 }
3472
3473 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3474 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3475 pv = htonl(0x30000); /* protocol version 3.0 */
3476
3477 packet = (char*) calloc(1, packet_len);
3478
3479 memcpy(packet + 4, &pv, 4);
3480
3481 /* copy "user" */
3482 memcpy(packet + 8, "user", 4);
3483
3484 /* copy username */
3485 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3486
3487 free(curproxy->check_req);
3488 curproxy->check_req = packet;
3489 curproxy->check_len = packet_len;
3490
3491 packet_len = htonl(packet_len);
3492 memcpy(packet, &packet_len, 4);
3493 cur_arg += 2;
3494 } else {
3495 /* unknown suboption - catchall */
3496 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3497 file, linenum, args[0], args[1]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501 } /* end while loop */
3502 }
3503 }
3504
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003505 else if (!strcmp(args[1], "redis-check")) {
3506 /* use REDIS PING request to check servers' health */
3507 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3508 err_code |= ERR_WARN;
3509
3510 free(curproxy->check_req);
3511 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003512 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003513 curproxy->options2 |= PR_O2_REDIS_CHK;
3514
3515 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3516 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3517 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3518 }
3519
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003520 else if (!strcmp(args[1], "mysql-check")) {
3521 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003522 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3523 err_code |= ERR_WARN;
3524
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003525 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003526 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003527 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003528 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003529
3530 /* This is an exemple of an MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
3531 * const char mysql40_client_auth_pkt[] = {
3532 * "\x0e\x00\x00" // packet length
3533 * "\x01" // packet number
3534 * "\x00\x00" // client capabilities
3535 * "\x00\x00\x01" // max packet
3536 * "haproxy\x00" // username (null terminated string)
3537 * "\x00" // filler (always 0x00)
3538 * "\x01\x00\x00" // packet length
3539 * "\x00" // packet number
3540 * "\x01" // COM_QUIT command
3541 * };
3542 */
3543
3544 if (*(args[2])) {
3545 int cur_arg = 2;
3546
3547 while (*(args[cur_arg])) {
3548 if (strcmp(args[cur_arg], "user") == 0) {
3549 char *mysqluser;
3550 int packetlen, reqlen, userlen;
3551
3552 /* suboption header - needs additional argument for it */
3553 if (*(args[cur_arg+1]) == 0) {
3554 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3555 file, linenum, args[0], args[1], args[cur_arg]);
3556 err_code |= ERR_ALERT | ERR_FATAL;
3557 goto out;
3558 }
3559 mysqluser = args[cur_arg + 1];
3560 userlen = strlen(mysqluser);
3561 packetlen = userlen + 7;
3562 reqlen = packetlen + 9;
3563
3564 free(curproxy->check_req);
3565 curproxy->check_req = (char *)calloc(1, reqlen);
3566 curproxy->check_len = reqlen;
3567
3568 snprintf(curproxy->check_req, 4, "%c%c%c",
3569 ((unsigned char) packetlen & 0xff),
3570 ((unsigned char) (packetlen >> 8) & 0xff),
3571 ((unsigned char) (packetlen >> 16) & 0xff));
3572
3573 curproxy->check_req[3] = 1;
Hervé COMMOWICK212f7782011-06-10 14:05:59 +02003574 curproxy->check_req[5] = 128;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003575 curproxy->check_req[8] = 1;
3576 memcpy(&curproxy->check_req[9], mysqluser, userlen);
3577 curproxy->check_req[9 + userlen + 1 + 1] = 1;
3578 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
3579 cur_arg += 2;
3580 } else {
3581 /* unknown suboption - catchall */
3582 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3583 file, linenum, args[0], args[1]);
3584 err_code |= ERR_ALERT | ERR_FATAL;
3585 goto out;
3586 }
3587 } /* end while loop */
3588 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003589 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003590 else if (!strcmp(args[1], "ldap-check")) {
3591 /* use LDAP request to check servers' health */
3592 free(curproxy->check_req);
3593 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003594 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02003595 curproxy->options2 |= PR_O2_LDAP_CHK;
3596
3597 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
3598 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
3599 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
3600 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003601 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02003602 int cur_arg;
3603
3604 /* insert x-forwarded-for field, but not for the IP address listed as an except.
3605 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003606 */
Ross Westaf72a1d2008-08-03 10:51:45 +02003607
Willy Tarreau87cf5142011-08-19 22:57:24 +02003608 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02003609
3610 free(curproxy->fwdfor_hdr_name);
3611 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
3612 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
3613
3614 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
3615 cur_arg = 2;
3616 while (*(args[cur_arg])) {
3617 if (!strcmp(args[cur_arg], "except")) {
3618 /* suboption except - needs additional argument for it */
3619 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
3620 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3621 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003624 }
3625 /* flush useless bits */
3626 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02003627 cur_arg += 2;
3628 } else if (!strcmp(args[cur_arg], "header")) {
3629 /* suboption header - needs additional argument for it */
3630 if (*(args[cur_arg+1]) == 0) {
3631 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3632 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02003635 }
3636 free(curproxy->fwdfor_hdr_name);
3637 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
3638 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
3639 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02003640 } else if (!strcmp(args[cur_arg], "if-none")) {
3641 curproxy->options &= ~PR_O_FF_ALWAYS;
3642 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003643 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02003644 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02003645 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02003646 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003649 }
Ross Westaf72a1d2008-08-03 10:51:45 +02003650 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02003651 }
Maik Broemme2850cb42009-04-17 18:53:21 +02003652 else if (!strcmp(args[1], "originalto")) {
3653 int cur_arg;
3654
3655 /* insert x-original-to field, but not for the IP address listed as an except.
3656 * set default options (ie: bitfield, header name, etc)
3657 */
3658
3659 curproxy->options |= PR_O_ORGTO;
3660
3661 free(curproxy->orgto_hdr_name);
3662 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
3663 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
3664
Willy Tarreau87cf5142011-08-19 22:57:24 +02003665 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02003666 cur_arg = 2;
3667 while (*(args[cur_arg])) {
3668 if (!strcmp(args[cur_arg], "except")) {
3669 /* suboption except - needs additional argument for it */
3670 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
3671 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
3672 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003673 err_code |= ERR_ALERT | ERR_FATAL;
3674 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003675 }
3676 /* flush useless bits */
3677 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
3678 cur_arg += 2;
3679 } else if (!strcmp(args[cur_arg], "header")) {
3680 /* suboption header - needs additional argument for it */
3681 if (*(args[cur_arg+1]) == 0) {
3682 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
3683 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_ALERT | ERR_FATAL;
3685 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003686 }
3687 free(curproxy->orgto_hdr_name);
3688 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
3689 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
3690 cur_arg += 2;
3691 } else {
3692 /* unknown suboption - catchall */
3693 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
3694 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02003697 }
3698 } /* end while loop */
3699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 else {
3701 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_ALERT | ERR_FATAL;
3703 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 }
Willy Tarreau93893792009-07-23 13:19:11 +02003705 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003706 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003707 else if (!strcmp(args[0], "default_backend")) {
3708 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003709 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003710
3711 if (*(args[1]) == 0) {
3712 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003713 err_code |= ERR_ALERT | ERR_FATAL;
3714 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003715 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003716 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003717 curproxy->defbe.name = strdup(args[1]);
3718 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01003720 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003722
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003723 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
3724 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003725 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003726 /* enable reconnections to dispatch */
3727 curproxy->options |= PR_O_REDISP;
3728 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003729 else if (!strcmp(args[0], "http-check")) {
3730 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003731 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01003732
3733 if (strcmp(args[1], "disable-on-404") == 0) {
3734 /* enable a graceful server shutdown on an HTTP 404 response */
3735 curproxy->options |= PR_O_DISABLE404;
3736 }
Willy Tarreauef781042010-01-27 11:53:01 +01003737 else if (strcmp(args[1], "send-state") == 0) {
3738 /* enable emission of the apparent state of a server in HTTP checks */
3739 curproxy->options2 |= PR_O2_CHK_SNDST;
3740 }
Willy Tarreaubd741542010-03-16 18:46:54 +01003741 else if (strcmp(args[1], "expect") == 0) {
3742 const char *ptr_arg;
3743 int cur_arg;
3744
3745 if (curproxy->options2 & PR_O2_EXP_TYPE) {
3746 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
3747 err_code |= ERR_ALERT | ERR_FATAL;
3748 goto out;
3749 }
3750
3751 cur_arg = 2;
3752 /* consider exclamation marks, sole or at the beginning of a word */
3753 while (*(ptr_arg = args[cur_arg])) {
3754 while (*ptr_arg == '!') {
3755 curproxy->options2 ^= PR_O2_EXP_INV;
3756 ptr_arg++;
3757 }
3758 if (*ptr_arg)
3759 break;
3760 cur_arg++;
3761 }
3762 /* now ptr_arg points to the beginning of a word past any possible
3763 * exclamation mark, and cur_arg is the argument which holds this word.
3764 */
3765 if (strcmp(ptr_arg, "status") == 0) {
3766 if (!*(args[cur_arg + 1])) {
3767 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3768 file, linenum, args[0], args[1], ptr_arg);
3769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
3772 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003773 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003774 curproxy->expect_str = strdup(args[cur_arg + 1]);
3775 }
3776 else if (strcmp(ptr_arg, "string") == 0) {
3777 if (!*(args[cur_arg + 1])) {
3778 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
3779 file, linenum, args[0], args[1], ptr_arg);
3780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
3782 }
3783 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003784 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01003785 curproxy->expect_str = strdup(args[cur_arg + 1]);
3786 }
3787 else if (strcmp(ptr_arg, "rstatus") == 0) {
3788 if (!*(args[cur_arg + 1])) {
3789 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3790 file, linenum, args[0], args[1], ptr_arg);
3791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
3793 }
3794 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003795 free(curproxy->expect_str);
3796 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3797 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003798 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3799 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3800 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3801 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
3804 }
3805 }
3806 else if (strcmp(ptr_arg, "rstring") == 0) {
3807 if (!*(args[cur_arg + 1])) {
3808 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
3809 file, linenum, args[0], args[1], ptr_arg);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003814 free(curproxy->expect_str);
3815 if (curproxy->expect_regex) regfree(curproxy->expect_regex);
3816 curproxy->expect_str = strdup(args[cur_arg + 1]);
Willy Tarreaubd741542010-03-16 18:46:54 +01003817 curproxy->expect_regex = calloc(1, sizeof(regex_t));
3818 if (regcomp(curproxy->expect_regex, args[cur_arg + 1], REG_EXTENDED) != 0) {
3819 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s'.\n",
3820 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1]);
3821 err_code |= ERR_ALERT | ERR_FATAL;
3822 goto out;
3823 }
3824 }
3825 else {
3826 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
3827 file, linenum, args[0], args[1], ptr_arg);
3828 err_code |= ERR_ALERT | ERR_FATAL;
3829 goto out;
3830 }
3831 }
Willy Tarreau48494c02007-11-30 10:41:39 +01003832 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003833 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 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01003836 }
3837 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01003838 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02003839 if (curproxy == &defproxy) {
3840 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003841 err_code |= ERR_ALERT | ERR_FATAL;
3842 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003843 }
3844
Willy Tarreaub80c2302007-11-30 20:51:32 +01003845 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003847
3848 if (strcmp(args[1], "fail") == 0) {
3849 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01003850 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003851 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3852 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003853 err_code |= ERR_ALERT | ERR_FATAL;
3854 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003855 }
3856
Willy Tarreauef6494c2010-01-28 17:12:36 +01003857 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2)) == NULL) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01003858 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
3859 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_ALERT | ERR_FATAL;
3861 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003862 }
3863 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
3864 }
3865 else {
3866 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01003869 }
3870 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003871#ifdef TPROXY
3872 else if (!strcmp(args[0], "transparent")) {
3873 /* enable transparent proxy connections */
3874 curproxy->options |= PR_O_TRANSP;
3875 }
3876#endif
3877 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003878 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003879 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003880
Willy Tarreaubaaee002006-06-26 02:48:02 +02003881 if (*(args[1]) == 0) {
3882 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003883 err_code |= ERR_ALERT | ERR_FATAL;
3884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003885 }
3886 curproxy->maxconn = atol(args[1]);
3887 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003888 else if (!strcmp(args[0], "backlog")) { /* backlog */
3889 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003890 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003891
3892 if (*(args[1]) == 0) {
3893 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01003896 }
3897 curproxy->backlog = atol(args[1]);
3898 }
Willy Tarreau86034312006-12-29 00:10:33 +01003899 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003900 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02003901 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003902
Willy Tarreau86034312006-12-29 00:10:33 +01003903 if (*(args[1]) == 0) {
3904 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003905 err_code |= ERR_ALERT | ERR_FATAL;
3906 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01003907 }
3908 curproxy->fullconn = atol(args[1]);
3909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003910 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
3911 if (*(args[1]) == 0) {
3912 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003916 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
3917 if (err) {
3918 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
3919 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003922 }
3923 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003924 }
3925 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01003926 struct sockaddr_storage *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 if (curproxy == &defproxy) {
3928 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003932 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003933 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003934
Willy Tarreaubaaee002006-06-26 02:48:02 +02003935 if (strchr(args[1], ':') == NULL) {
3936 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
Willy Tarreaud5191e72010-02-09 20:50:45 +01003940 sk = str2sa(args[1]);
3941 if (!sk) {
3942 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
3943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
3945 }
3946 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003947 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003948 }
3949 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003950 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003952
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02003953 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01003954 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
3955 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02003956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02003958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003959 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003960 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
3961 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3962 err_code |= ERR_WARN;
3963
3964 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
3965 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3966 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
3967 }
3968 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
3969 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3970 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
3971 }
Willy Tarreau798a39c2010-11-24 15:04:29 +01003972 else if (strcmp(args[1], "avalanche") == 0) { /* use full hash before map-based hashing */
3973 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
3974 curproxy->lbprm.algo |= BE_LB_HASH_AVAL;
3975 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003976 else {
Willy Tarreau798a39c2010-11-24 15:04:29 +01003977 Alert("parsing [%s:%d] : '%s' only supports 'avalanche', 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02003978 err_code |= ERR_ALERT | ERR_FATAL;
3979 goto out;
3980 }
3981 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003982 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003983 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003984 char *rport, *raddr;
3985 short realport = 0;
3986 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003988 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003990 err_code |= ERR_ALERT | ERR_FATAL;
3991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003993 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003995
3996 if (!*args[2]) {
3997 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
3998 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003999 err_code |= ERR_ALERT | ERR_FATAL;
4000 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004001 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004002
4003 err = invalid_char(args[1]);
4004 if (err) {
4005 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
4006 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004007 err_code |= ERR_ALERT | ERR_FATAL;
4008 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01004009 }
4010
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004011 if (!defsrv) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004012 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004013
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01004014 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
4015 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
4016 err_code |= ERR_ALERT | ERR_ABORT;
4017 goto out;
4018 }
4019
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004020 /* the servers are linked backwards first */
4021 newsrv->next = curproxy->srv;
4022 curproxy->srv = newsrv;
4023 newsrv->proxy = curproxy;
4024 newsrv->conf.file = file;
4025 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004026
Simon Hormanaf514952011-06-21 14:34:57 +09004027 LIST_INIT(&newsrv->actconns);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004028 LIST_INIT(&newsrv->pendconns);
4029 do_check = 0;
4030 newsrv->state = SRV_RUNNING; /* early server setup */
4031 newsrv->last_change = now.tv_sec;
4032 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004033
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004034 /* several ways to check the port component :
David du Colombier9842ff12011-03-17 10:40:28 +01004035 * - IP => port=+0, relative (IPv4 only)
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004036 * - IP: => port=+0, relative
4037 * - IP:N => port=N, absolute
4038 * - IP:+N => port=+N, relative
4039 * - IP:-N => port=-N, relative
4040 */
4041 raddr = strdup(args[2]);
Willy Tarreaufab5a432011-03-04 15:31:53 +01004042 rport = strrchr(raddr, ':');
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004043 if (rport) {
4044 *rport++ = 0;
4045 realport = atol(rport);
4046 if (!isdigit((unsigned char)*rport))
4047 newsrv->state |= SRV_MAPPORTS;
4048 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004050
Willy Tarreaufab5a432011-03-04 15:31:53 +01004051 sk = str2ip(raddr);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004052 free(raddr);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004053 if (!sk) {
4054 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[2]);
4055 err_code |= ERR_ALERT | ERR_FATAL;
4056 goto out;
4057 }
4058 newsrv->addr = *sk;
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004059 set_host_port(&newsrv->addr, realport);
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004060
4061 newsrv->check_port = curproxy->defsrv.check_port;
4062 newsrv->inter = curproxy->defsrv.inter;
4063 newsrv->fastinter = curproxy->defsrv.fastinter;
4064 newsrv->downinter = curproxy->defsrv.downinter;
4065 newsrv->rise = curproxy->defsrv.rise;
4066 newsrv->fall = curproxy->defsrv.fall;
4067 newsrv->maxqueue = curproxy->defsrv.maxqueue;
4068 newsrv->minconn = curproxy->defsrv.minconn;
4069 newsrv->maxconn = curproxy->defsrv.maxconn;
4070 newsrv->slowstart = curproxy->defsrv.slowstart;
4071 newsrv->onerror = curproxy->defsrv.onerror;
4072 newsrv->consecutive_errors_limit
4073 = curproxy->defsrv.consecutive_errors_limit;
4074 newsrv->uweight = newsrv->iweight
4075 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004076
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004077 newsrv->curfd = -1; /* no health-check in progress */
4078 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004079
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004080 cur_arg = 3;
4081 } else {
4082 newsrv = &curproxy->defsrv;
4083 cur_arg = 1;
4084 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004085
Willy Tarreaubaaee002006-06-26 02:48:02 +02004086 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004087 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004088 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004089
4090 if (!*args[cur_arg + 1]) {
4091 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4092 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004095 }
4096
4097 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004098 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004099
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004100 if (newsrv->puid <= 0) {
4101 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004102 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004105 }
4106
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004107 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
4108 if (node) {
4109 struct server *target = container_of(node, struct server, conf.id);
4110 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
4111 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
4112 err_code |= ERR_ALERT | ERR_FATAL;
4113 goto out;
4114 }
4115 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01004116 cur_arg += 2;
4117 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004118 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004119 newsrv->cookie = strdup(args[cur_arg + 1]);
4120 newsrv->cklen = strlen(args[cur_arg + 1]);
4121 cur_arg += 2;
4122 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004123 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01004124 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
4125 newsrv->rdr_len = strlen(args[cur_arg + 1]);
4126 cur_arg += 2;
4127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004129 if (!*args[cur_arg + 1]) {
4130 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4131 file, linenum, args[cur_arg]);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
4134 }
4135
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004137 if (newsrv->rise <= 0) {
4138 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4139 file, linenum, args[cur_arg]);
4140 err_code |= ERR_ALERT | ERR_FATAL;
4141 goto out;
4142 }
4143
Willy Tarreau96839092010-03-29 10:02:24 +02004144 if (newsrv->health)
4145 newsrv->health = newsrv->rise;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 cur_arg += 2;
4147 }
4148 else if (!strcmp(args[cur_arg], "fall")) {
4149 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02004150
4151 if (!*args[cur_arg + 1]) {
4152 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4153 file, linenum, args[cur_arg]);
4154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
4156 }
4157
4158 if (newsrv->fall <= 0) {
4159 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
4160 file, linenum, args[cur_arg]);
4161 err_code |= ERR_ALERT | ERR_FATAL;
4162 goto out;
4163 }
4164
Willy Tarreaubaaee002006-06-26 02:48:02 +02004165 cur_arg += 2;
4166 }
4167 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004168 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4169 if (err) {
4170 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
4171 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004174 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004175 if (val <= 0) {
4176 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4177 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004178 err_code |= ERR_ALERT | ERR_FATAL;
4179 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004180 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004181 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004182 cur_arg += 2;
4183 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004184 else if (!strcmp(args[cur_arg], "fastinter")) {
4185 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4186 if (err) {
4187 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
4188 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004191 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004192 if (val <= 0) {
4193 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4194 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004197 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004198 newsrv->fastinter = val;
4199 cur_arg += 2;
4200 }
4201 else if (!strcmp(args[cur_arg], "downinter")) {
4202 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
4203 if (err) {
4204 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
4205 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004208 }
Willy Tarreaue3838802009-03-21 18:58:32 +01004209 if (val <= 0) {
4210 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4211 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004214 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01004215 newsrv->downinter = val;
4216 cur_arg += 2;
4217 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004218 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004219 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004220 if (!sk) {
4221 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
4224 }
4225 newsrv->check_addr = *sk;
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02004226 cur_arg += 2;
4227 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004228 else if (!strcmp(args[cur_arg], "port")) {
4229 newsrv->check_port = atol(args[cur_arg + 1]);
4230 cur_arg += 2;
4231 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004232 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 newsrv->state |= SRV_BACKUP;
4234 cur_arg ++;
4235 }
Simon Hormanfa461682011-06-25 09:39:49 +09004236 else if (!defsrv && !strcmp(args[cur_arg], "non-stick")) {
4237 newsrv->state |= SRV_NON_STICK;
4238 cur_arg ++;
4239 }
Willy Tarreau5ab04ec2011-03-20 10:32:26 +01004240 else if (!defsrv && !strcmp(args[cur_arg], "send-proxy")) {
4241 newsrv->state |= SRV_SEND_PROXY;
4242 cur_arg ++;
4243 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004244 else if (!strcmp(args[cur_arg], "weight")) {
4245 int w;
4246 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02004247 if (w < 0 || w > 256) {
4248 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004249 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02004250 err_code |= ERR_ALERT | ERR_FATAL;
4251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004252 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02004253 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004254 cur_arg += 2;
4255 }
4256 else if (!strcmp(args[cur_arg], "minconn")) {
4257 newsrv->minconn = atol(args[cur_arg + 1]);
4258 cur_arg += 2;
4259 }
4260 else if (!strcmp(args[cur_arg], "maxconn")) {
4261 newsrv->maxconn = atol(args[cur_arg + 1]);
4262 cur_arg += 2;
4263 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02004264 else if (!strcmp(args[cur_arg], "maxqueue")) {
4265 newsrv->maxqueue = atol(args[cur_arg + 1]);
4266 cur_arg += 2;
4267 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01004268 else if (!strcmp(args[cur_arg], "slowstart")) {
4269 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01004270 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004271 if (err) {
4272 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
4273 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004276 }
Willy Tarreau4554bc12010-03-26 10:40:49 +01004277 if (val < 0) {
Willy Tarreaue3838802009-03-21 18:58:32 +01004278 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
4279 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01004282 }
Willy Tarreau3259e332007-12-03 01:51:45 +01004283 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01004284 cur_arg += 2;
4285 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004286 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004287
4288 if (!*args[cur_arg + 1]) {
4289 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
4290 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004293 }
4294
4295 newsrv->trackit = strdup(args[cur_arg + 1]);
4296
4297 cur_arg += 2;
4298 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004299 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 global.maxsock++;
4301 do_check = 1;
4302 cur_arg += 1;
4303 }
Willy Tarreau96839092010-03-29 10:02:24 +02004304 else if (!defsrv && !strcmp(args[cur_arg], "disabled")) {
4305 newsrv->state |= SRV_MAINTAIN;
4306 newsrv->state &= ~SRV_RUNNING;
4307 newsrv->health = 0;
4308 cur_arg += 1;
4309 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004310 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004311 if (!strcmp(args[cur_arg + 1], "none"))
4312 newsrv->observe = HANA_OBS_NONE;
4313 else if (!strcmp(args[cur_arg + 1], "layer4"))
4314 newsrv->observe = HANA_OBS_LAYER4;
4315 else if (!strcmp(args[cur_arg + 1], "layer7")) {
4316 if (curproxy->mode != PR_MODE_HTTP) {
4317 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
4318 file, linenum, args[cur_arg + 1]);
4319 err_code |= ERR_ALERT;
4320 }
4321 newsrv->observe = HANA_OBS_LAYER7;
4322 }
4323 else {
4324 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004325 "'layer4', 'layer7' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004326 file, linenum, args[cur_arg], args[cur_arg + 1]);
4327 err_code |= ERR_ALERT | ERR_FATAL;
4328 goto out;
4329 }
4330
4331 cur_arg += 2;
4332 }
4333 else if (!strcmp(args[cur_arg], "on-error")) {
4334 if (!strcmp(args[cur_arg + 1], "fastinter"))
4335 newsrv->onerror = HANA_ONERR_FASTINTER;
4336 else if (!strcmp(args[cur_arg + 1], "fail-check"))
4337 newsrv->onerror = HANA_ONERR_FAILCHK;
4338 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
4339 newsrv->onerror = HANA_ONERR_SUDDTH;
4340 else if (!strcmp(args[cur_arg + 1], "mark-down"))
4341 newsrv->onerror = HANA_ONERR_MARKDWN;
4342 else {
4343 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
Willy Tarreau53621e02010-10-22 14:53:40 +02004344 "'fail-check', 'sudden-death' or 'mark-down' but got '%s'\n",
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004345 file, linenum, args[cur_arg], args[cur_arg + 1]);
4346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
4348 }
4349
4350 cur_arg += 2;
4351 }
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004352 else if (!strcmp(args[cur_arg], "on-marked-down")) {
4353 if (!strcmp(args[cur_arg + 1], "shutdown-sessions"))
4354 newsrv->onmarkeddown = HANA_ONMARKEDDOWN_SHUTDOWNSESSIONS;
4355 else {
4356 Alert("parsing [%s:%d]: '%s' expects 'shutdown-sessions' but got '%s'\n",
4357 file, linenum, args[cur_arg], args[cur_arg + 1]);
4358 err_code |= ERR_ALERT | ERR_FATAL;
4359 goto out;
4360 }
4361
4362 cur_arg += 2;
4363 }
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004364 else if (!strcmp(args[cur_arg], "error-limit")) {
4365 if (!*args[cur_arg + 1]) {
4366 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
4367 file, linenum, args[cur_arg]);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371
4372 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
4373
4374 if (newsrv->consecutive_errors_limit <= 0) {
4375 Alert("parsing [%s:%d]: %s has to be > 0.\n",
4376 file, linenum, args[cur_arg]);
4377 err_code |= ERR_ALERT | ERR_FATAL;
4378 goto out;
4379 }
Willy Tarreauf53b25d2010-03-15 19:40:37 +01004380 cur_arg += 2;
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01004381 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004382 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004383 int port_low, port_high;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004384 struct sockaddr_storage *sk;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004385
Willy Tarreaubaaee002006-06-26 02:48:02 +02004386 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004387#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004388 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004389 file, linenum, "source", "usesrc");
4390#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004391 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02004392 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004393#endif
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 }
4397 newsrv->state |= SRV_BIND_SRC;
Willy Tarreaud5191e72010-02-09 20:50:45 +01004398 sk = str2sa_range(args[cur_arg + 1], &port_low, &port_high);
4399 if (!sk) {
4400 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4401 err_code |= ERR_ALERT | ERR_FATAL;
4402 goto out;
4403 }
4404 newsrv->source_addr = *sk;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004405
4406 if (port_low != port_high) {
4407 int i;
4408 if (port_low <= 0 || port_low > 65535 ||
4409 port_high <= 0 || port_high > 65535 ||
4410 port_low > port_high) {
4411 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
4412 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_FATAL;
4414 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02004415 }
4416 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
4417 for (i = 0; i < newsrv->sport_range->size; i++)
4418 newsrv->sport_range->ports[i] = port_low + i;
4419 }
4420
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004422 while (*(args[cur_arg])) {
4423 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004424#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4425#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004426 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
4427 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
4428 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004431 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004432#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004433 if (!*args[cur_arg + 1]) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004434 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', 'clientip', or 'hdr_ip(name,#)' as argument.\n",
Willy Tarreauc76721d2009-02-04 20:20:58 +01004435 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004436 err_code |= ERR_ALERT | ERR_FATAL;
4437 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004438 }
4439 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004440 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004441 newsrv->state |= SRV_TPROXY_CLI;
4442 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004443 newsrv->state &= ~SRV_TPROXY_MASK;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004444 newsrv->state |= SRV_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004445 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4446 char *name, *end;
4447
4448 name = args[cur_arg+1] + 7;
4449 while (isspace(*name))
4450 name++;
4451
4452 end = name;
4453 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4454 end++;
4455
4456 newsrv->state &= ~SRV_TPROXY_MASK;
4457 newsrv->state |= SRV_TPROXY_DYN;
4458 newsrv->bind_hdr_name = calloc(1, end - name + 1);
4459 newsrv->bind_hdr_len = end - name;
4460 memcpy(newsrv->bind_hdr_name, name, end - name);
4461 newsrv->bind_hdr_name[end-name] = '\0';
4462 newsrv->bind_hdr_occ = -1;
4463
4464 /* now look for an occurrence number */
4465 while (isspace(*end))
4466 end++;
4467 if (*end == ',') {
4468 end++;
4469 name = end;
4470 if (*end == '-')
4471 end++;
4472 while (isdigit(*end))
4473 end++;
4474 newsrv->bind_hdr_occ = strl2ic(name, end-name);
4475 }
4476
4477 if (newsrv->bind_hdr_occ < -MAX_HDR_HISTORY) {
4478 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4479 " occurrences values smaller than %d.\n",
4480 file, linenum, MAX_HDR_HISTORY);
4481 err_code |= ERR_ALERT | ERR_FATAL;
4482 goto out;
4483 }
Willy Tarreauc76721d2009-02-04 20:20:58 +01004484 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004485 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004486 if (!sk) {
4487 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
4490 }
4491 newsrv->tproxy_addr = *sk;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004492 newsrv->state |= SRV_TPROXY_ADDR;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004493 }
4494 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004495#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01004496 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004497#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004498 cur_arg += 2;
4499 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004500#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01004501 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004502 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004505#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
4506 } /* "usesrc" */
4507
4508 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4509#ifdef SO_BINDTODEVICE
4510 if (!*args[cur_arg + 1]) {
4511 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4512 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004513 err_code |= ERR_ALERT | ERR_FATAL;
4514 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01004515 }
4516 if (newsrv->iface_name)
4517 free(newsrv->iface_name);
4518
4519 newsrv->iface_name = strdup(args[cur_arg + 1]);
4520 newsrv->iface_len = strlen(newsrv->iface_name);
4521 global.last_checks |= LSTCHK_NETADM;
4522#else
4523 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4524 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01004527#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01004528 cur_arg += 2;
4529 continue;
4530 }
4531 /* this keyword in not an option of "source" */
4532 break;
4533 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004534 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004535 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004536 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4537 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_ALERT | ERR_FATAL;
4539 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004540 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004541 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004542 if (!defsrv)
Simon Hormane0d1bfb2011-06-21 14:34:58 +09004543 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'on-marked-down', 'error-limit', 'check', 'disabled', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'send-proxy', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004544 file, linenum, newsrv->id);
4545 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01004546 Alert("parsing [%s:%d]: default-server only supports options 'on-error', 'error-limit', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'port', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004547 file, linenum);
4548
Willy Tarreau93893792009-07-23 13:19:11 +02004549 err_code |= ERR_ALERT | ERR_FATAL;
4550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004551 }
4552 }
4553
4554 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004555 if (newsrv->trackit) {
4556 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
4557 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004558 err_code |= ERR_ALERT | ERR_FATAL;
4559 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004560 }
4561
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004562 /* try to get the port from check_addr if check_port not set */
4563 if (!newsrv->check_port)
4564 newsrv->check_port = get_host_port(&newsrv->check_addr);
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02004565
Willy Tarreaubaaee002006-06-26 02:48:02 +02004566 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
4567 newsrv->check_port = realport; /* by default */
4568 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01004569 /* not yet valid, because no port was set on
4570 * the server either. We'll check if we have
4571 * a known port on the first listener.
4572 */
Willy Tarreau86ad42c2011-08-27 12:29:07 +02004573 struct listener *l = curproxy->listen;
4574 while (l && !(newsrv->check_port = get_host_port(&l->addr)))
4575 l = l->next;
Willy Tarreauef00b502007-01-07 02:40:09 +01004576 }
4577 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004578 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
4579 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02004580 err_code |= ERR_ALERT | ERR_FATAL;
4581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004583
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004584 /* Allocate buffer for partial check results... */
Willy Tarreau43961d52010-10-04 20:39:20 +02004585 if ((newsrv->check_data = calloc(global.tune.chksize, sizeof(char))) == NULL) {
Cyril Bontéc9f825f2010-03-17 18:56:31 +01004586 Alert("parsing [%s:%d] : out of memory while allocating check buffer.\n", file, linenum);
4587 err_code |= ERR_ALERT | ERR_ABORT;
4588 goto out;
4589 }
4590
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02004591 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004592 newsrv->state |= SRV_CHECKED;
4593 }
4594
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004595 if (!defsrv) {
4596 if (newsrv->state & SRV_BACKUP)
4597 curproxy->srv_bck++;
4598 else
4599 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01004600
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004601 newsrv->prev_state = newsrv->state;
4602 }
William Lallemanda73203e2012-03-12 12:48:57 +01004603 }
4604
4605 else if (strcmp(args[0], "unique-id-format") == 0) {
4606 if (!*(args[1])) {
4607 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4608 err_code |= ERR_ALERT | ERR_FATAL;
4609 goto out;
4610 }
4611 parse_logformat_string(args[1], curproxy, &curproxy->format_unique_id, PR_MODE_HTTP);
William Lallemand723b73a2012-02-08 16:37:49 +01004612 }
William Lallemanda73203e2012-03-12 12:48:57 +01004613
4614 else if (strcmp(args[0], "unique-id-header") == 0) {
4615 if (!*(args[1])) {
4616 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4617 err_code |= ERR_ALERT | ERR_FATAL;
4618 goto out;
4619 }
4620 free(curproxy->header_unique_id);
4621 curproxy->header_unique_id = strdup(args[1]);
4622 }
4623
William Lallemand723b73a2012-02-08 16:37:49 +01004624 else if (strcmp(args[0], "log-format") == 0) {
4625 if (!*(args[1])) {
4626 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4627 err_code |= ERR_ALERT | ERR_FATAL;
4628 goto out;
4629 }
William Lallemand1d705562012-03-12 12:46:41 +01004630 parse_logformat_string(args[1], curproxy, &curproxy->logformat, curproxy->mode);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004631 }
William Lallemand723b73a2012-02-08 16:37:49 +01004632
William Lallemand0f99e342011-10-12 17:50:54 +02004633 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4634 /* delete previous herited or defined syslog servers */
4635 struct logsrv *back;
4636
4637 if (*(args[1]) != 0) {
4638 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642
William Lallemand723b73a2012-02-08 16:37:49 +01004643 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4644 LIST_DEL(&tmplogsrv->list);
4645 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004646 }
4647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004649 struct logsrv *logsrv;
4650
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004652 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004653 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004654 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004655 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004656 LIST_INIT(&node->list);
4657 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4658 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004659 }
4660 else if (*(args[1]) && *(args[2])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004661
4662 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004663
William Lallemand0f99e342011-10-12 17:50:54 +02004664 logsrv->facility = get_log_facility(args[2]);
4665 if (logsrv->facility < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
4669
Willy Tarreaubaaee002006-06-26 02:48:02 +02004670 }
4671
William Lallemand0f99e342011-10-12 17:50:54 +02004672 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 if (*(args[3])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004674 logsrv->level = get_log_level(args[3]);
4675 if (logsrv->level < 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004676 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
4679
Willy Tarreaubaaee002006-06-26 02:48:02 +02004680 }
4681 }
4682
William Lallemand0f99e342011-10-12 17:50:54 +02004683 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004684 if (*(args[4])) {
William Lallemand0f99e342011-10-12 17:50:54 +02004685 logsrv->minlvl = get_log_level(args[4]);
4686 if (logsrv->level < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004687 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
4690
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004691 }
4692 }
4693
Robert Tsai81ae1952007-12-05 10:47:29 +01004694 if (args[1][0] == '/') {
David du Colombier11bcb6c2011-03-24 12:23:00 +01004695 struct sockaddr_storage *sk = (struct sockaddr_storage *)str2sun(args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004696 if (!sk) {
4697 Alert("parsing [%s:%d] : Socket path '%s' too long (max %d)\n", file, linenum,
David du Colombier11bcb6c2011-03-24 12:23:00 +01004698 args[1], (int)sizeof(((struct sockaddr_un *)sk)->sun_path) - 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
4701 }
William Lallemand0f99e342011-10-12 17:50:54 +02004702 logsrv->addr = *sk;
Robert Tsai81ae1952007-12-05 10:47:29 +01004703 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004704 struct sockaddr_storage *sk = str2sa(args[1]);
David du Colombier11bcb6c2011-03-24 12:23:00 +01004705 if (!sk) {
Willy Tarreaud5191e72010-02-09 20:50:45 +01004706 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709 }
William Lallemand0f99e342011-10-12 17:50:54 +02004710 logsrv->addr = *sk;
4711 if (!get_host_port(&logsrv->addr))
4712 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004713 }
William Lallemand0f99e342011-10-12 17:50:54 +02004714
4715 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 }
4717 else {
4718 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4719 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_ALERT | ERR_FATAL;
4721 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004722 }
4723 }
4724 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004725 int cur_arg;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004726 struct sockaddr_storage *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004727
Willy Tarreau977b8e42006-12-29 14:19:17 +01004728 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004729 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004730
Willy Tarreaubaaee002006-06-26 02:48:02 +02004731 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004732 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4733 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004736 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004737
4738 /* we must first clear any optional default setting */
4739 curproxy->options &= ~PR_O_TPXY_MASK;
4740 free(curproxy->iface_name);
4741 curproxy->iface_name = NULL;
4742 curproxy->iface_len = 0;
4743
Willy Tarreaud5191e72010-02-09 20:50:45 +01004744 sk = str2sa(args[1]);
4745 if (!sk) {
4746 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[1]);
4747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
4749 }
4750 curproxy->source_addr = *sk;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004751 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004752
4753 cur_arg = 2;
4754 while (*(args[cur_arg])) {
4755 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004756#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
4757#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004758 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
4759 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
4760 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004763 }
4764#endif
4765 if (!*args[cur_arg + 1]) {
4766 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
4767 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004768 err_code |= ERR_ALERT | ERR_FATAL;
4769 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004770 }
4771
4772 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004773 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004774 curproxy->options |= PR_O_TPXY_CLI;
4775 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreaubce70882009-09-07 11:51:47 +02004776 curproxy->options &= ~PR_O_TPXY_MASK;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004777 curproxy->options |= PR_O_TPXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02004778 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
4779 char *name, *end;
4780
4781 name = args[cur_arg+1] + 7;
4782 while (isspace(*name))
4783 name++;
4784
4785 end = name;
4786 while (*end && !isspace(*end) && *end != ',' && *end != ')')
4787 end++;
4788
4789 curproxy->options &= ~PR_O_TPXY_MASK;
4790 curproxy->options |= PR_O_TPXY_DYN;
4791 curproxy->bind_hdr_name = calloc(1, end - name + 1);
4792 curproxy->bind_hdr_len = end - name;
4793 memcpy(curproxy->bind_hdr_name, name, end - name);
4794 curproxy->bind_hdr_name[end-name] = '\0';
4795 curproxy->bind_hdr_occ = -1;
4796
4797 /* now look for an occurrence number */
4798 while (isspace(*end))
4799 end++;
4800 if (*end == ',') {
4801 end++;
4802 name = end;
4803 if (*end == '-')
4804 end++;
4805 while (isdigit(*end))
4806 end++;
4807 curproxy->bind_hdr_occ = strl2ic(name, end-name);
4808 }
4809
4810 if (curproxy->bind_hdr_occ < -MAX_HDR_HISTORY) {
4811 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
4812 " occurrences values smaller than %d.\n",
4813 file, linenum, MAX_HDR_HISTORY);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
4816 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004817 } else {
David du Colombier6f5ccb12011-03-10 22:26:24 +01004818 struct sockaddr_storage *sk = str2sa(args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004819 if (!sk) {
4820 Alert("parsing [%s:%d] : Unknown host in '%s'\n", file, linenum, args[cur_arg + 1]);
4821 err_code |= ERR_ALERT | ERR_FATAL;
4822 goto out;
4823 }
4824 curproxy->tproxy_addr = *sk;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004825 curproxy->options |= PR_O_TPXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004826 }
4827 global.last_checks |= LSTCHK_NETADM;
4828#if !defined(CONFIG_HAP_LINUX_TPROXY)
4829 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004830#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004831#else /* no TPROXY support */
4832 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01004833 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004836#endif
4837 cur_arg += 2;
4838 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01004839 }
4840
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004841 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
4842#ifdef SO_BINDTODEVICE
4843 if (!*args[cur_arg + 1]) {
4844 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
4845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004848 }
4849 if (curproxy->iface_name)
4850 free(curproxy->iface_name);
4851
4852 curproxy->iface_name = strdup(args[cur_arg + 1]);
4853 curproxy->iface_len = strlen(curproxy->iface_name);
4854 global.last_checks |= LSTCHK_NETADM;
4855#else
4856 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
4857 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01004860#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004861 cur_arg += 2;
4862 continue;
4863 }
4864 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
4865 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02004866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004870 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
4871 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
4872 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02004873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01004875 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004876 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004877 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4879 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004883
4884 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004885 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004886 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004887 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 }
4890 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004891 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004892 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004893 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004894 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004896 }
4897 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004898 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004899 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004900 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004901 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004903 }
4904 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004905 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004906 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004907 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004908 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
4911 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004912 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004913 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004914 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004915 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004916 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004918 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004919 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004920 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004921 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004922 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004923 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004924 }
Willy Tarreaua496b602006-12-17 23:15:24 +01004925 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004926 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004927 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01004928 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004929 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004930 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004931 }
4932 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004933 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004934 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004935 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004936 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004937 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01004938 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004939 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004940 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004941 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004943 err_code |= ERR_ALERT | ERR_FATAL;
4944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01004946
4947 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004948 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004949 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004950 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004954 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004955 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004956 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004957 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004959 }
4960 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004961 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004962 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004963 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004964 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004966 }
4967 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004968 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004969 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004970 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004971 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004973 }
4974 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004975 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004976 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004977 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004978 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004980 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02004981 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01004982 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02004983 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01004984 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01004985 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02004986 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02004987 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004988 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01004989 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004990
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 if (curproxy == &defproxy) {
4992 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004996 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004997 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 if (*(args[1]) == 0) {
5000 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005004
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005005 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
5006 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5007 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5008 file, linenum, args[0]);
5009 err_code |= ERR_ALERT | ERR_FATAL;
5010 goto out;
5011 }
5012 err_code |= warnif_cond_requires_resp(cond, file, linenum);
5013 }
5014 else if (*args[2]) {
5015 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5016 file, linenum, args[0], args[2]);
5017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019 }
5020
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005021 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005022 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005023 wl->s = strdup(args[1]);
5024 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005025 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
5027 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005028 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005029 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5030 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005031 err_code |= ERR_ALERT | ERR_FATAL;
5032 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005034
Willy Tarreauade5ec42010-01-28 19:33:49 +01005035 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005036 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005037 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005038 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005039 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005040 }
5041 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005042 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005043 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005044 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005045 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005046 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005047 }
5048 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005049 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005050 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005051 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005052 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005053 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005054 }
5055 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005056 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005057 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5058 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005059 err_code |= ERR_ALERT | ERR_FATAL;
5060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005061 }
5062
Willy Tarreauade5ec42010-01-28 19:33:49 +01005063 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005064 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005065 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005066 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
5069 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005070 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005071 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005072 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005073 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005075 }
5076 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005077 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005078 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005079 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005080 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005082 }
5083 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005084 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005085
Willy Tarreaubaaee002006-06-26 02:48:02 +02005086 if (curproxy == &defproxy) {
5087 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005090 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005091 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005092 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005093
Willy Tarreaubaaee002006-06-26 02:48:02 +02005094 if (*(args[1]) == 0) {
5095 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005098 }
5099
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005100 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
5101 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2)) == NULL) {
5102 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition.\n",
5103 file, linenum, args[0]);
5104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
5106 }
5107 err_code |= warnif_cond_requires_req(cond, file, linenum);
5108 }
5109 else if (*args[2]) {
5110 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5111 file, linenum, args[0], args[2]);
5112 err_code |= ERR_ALERT | ERR_FATAL;
5113 goto out;
5114 }
5115
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005116 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005117 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005118 wl->s = strdup(args[1]);
5119 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005120 }
5121 else if (!strcmp(args[0], "errorloc") ||
5122 !strcmp(args[0], "errorloc302") ||
5123 !strcmp(args[0], "errorloc303")) { /* error location */
5124 int errnum, errlen;
5125 char *err;
5126
Willy Tarreau977b8e42006-12-29 14:19:17 +01005127 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005128 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005129
Willy Tarreaubaaee002006-06-26 02:48:02 +02005130 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005131 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005132 err_code |= ERR_ALERT | ERR_FATAL;
5133 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 }
5135
5136 errnum = atol(args[1]);
5137 if (!strcmp(args[0], "errorloc303")) {
5138 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
5139 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
5140 } else {
5141 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
5142 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
5143 }
5144
Willy Tarreau0f772532006-12-23 20:51:41 +01005145 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5146 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005147 chunk_destroy(&curproxy->errmsg[rc]);
5148 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005149 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005152
5153 if (rc >= HTTP_ERR_SIZE) {
5154 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5155 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 free(err);
5157 }
5158 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005159 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5160 int errnum, errlen, fd;
5161 char *err;
5162 struct stat stat;
5163
5164 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005165 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005166
5167 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005168 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005169 err_code |= ERR_ALERT | ERR_FATAL;
5170 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005171 }
5172
5173 fd = open(args[2], O_RDONLY);
5174 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5175 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5176 file, linenum, args[2], args[1]);
5177 if (fd >= 0)
5178 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005181 }
5182
Willy Tarreau27a674e2009-08-17 07:23:33 +02005183 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005184 errlen = stat.st_size;
5185 } else {
5186 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005187 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005188 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005189 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005190 }
5191
5192 err = malloc(errlen); /* malloc() must succeed during parsing */
5193 errnum = read(fd, err, errlen);
5194 if (errnum != errlen) {
5195 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5196 file, linenum, args[2], args[1]);
5197 close(fd);
5198 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005201 }
5202 close(fd);
5203
5204 errnum = atol(args[1]);
5205 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5206 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005207 chunk_destroy(&curproxy->errmsg[rc]);
5208 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005209 break;
5210 }
5211 }
5212
5213 if (rc >= HTTP_ERR_SIZE) {
5214 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5215 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005216 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005217 free(err);
5218 }
5219 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005221 struct cfg_kw_list *kwl;
5222 int index;
5223
5224 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5225 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5226 if (kwl->kw[index].section != CFG_LISTEN)
5227 continue;
5228 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5229 /* prepare error message just in case */
5230 snprintf(trash, sizeof(trash),
5231 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005232 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
5233 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005234 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005237 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005238 else if (rc > 0) {
5239 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_WARN;
5241 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005242 }
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005244 }
5245 }
5246 }
5247
Willy Tarreau6daf3432008-01-22 16:44:08 +01005248 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005249 err_code |= ERR_ALERT | ERR_FATAL;
5250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
Willy Tarreau93893792009-07-23 13:19:11 +02005252 out:
5253 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005254}
5255
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005256int
5257cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5258{
5259
5260 int err_code = 0;
5261 const char *err;
5262
5263 if (!strcmp(args[0], "userlist")) { /* new userlist */
5264 struct userlist *newul;
5265
5266 if (!*args[1]) {
5267 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5268 file, linenum, args[0]);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272
5273 err = invalid_char(args[1]);
5274 if (err) {
5275 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5276 file, linenum, *err, args[0], args[1]);
5277 err_code |= ERR_ALERT | ERR_FATAL;
5278 goto out;
5279 }
5280
5281 for (newul = userlist; newul; newul = newul->next)
5282 if (!strcmp(newul->name, args[1])) {
5283 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5284 file, linenum, args[1]);
5285 err_code |= ERR_WARN;
5286 goto out;
5287 }
5288
5289 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5290 if (!newul) {
5291 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5292 err_code |= ERR_ALERT | ERR_ABORT;
5293 goto out;
5294 }
5295
5296 newul->groupusers = calloc(MAX_AUTH_GROUPS, sizeof(char *));
5297 newul->name = strdup(args[1]);
5298
5299 if (!newul->groupusers | !newul->name) {
5300 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5301 err_code |= ERR_ALERT | ERR_ABORT;
5302 goto out;
5303 }
5304
5305 newul->next = userlist;
5306 userlist = newul;
5307
5308 } else if (!strcmp(args[0], "group")) { /* new group */
5309 int cur_arg, i;
5310 const char *err;
5311
5312 if (!*args[1]) {
5313 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5314 file, linenum, args[0]);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318
5319 err = invalid_char(args[1]);
5320 if (err) {
5321 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5322 file, linenum, *err, args[0], args[1]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326
5327 for(i = 0; i < userlist->grpcnt; i++)
5328 if (!strcmp(userlist->groups[i], args[1])) {
5329 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5330 file, linenum, args[1], userlist->name);
5331 err_code |= ERR_ALERT;
5332 goto out;
5333 }
5334
5335 if (userlist->grpcnt >= MAX_AUTH_GROUPS) {
5336 Alert("parsing [%s:%d]: too many groups (%u) in in userlist '%s' while adding group '%s'.\n",
5337 file, linenum, MAX_AUTH_GROUPS, userlist->name, args[1]);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341
5342 cur_arg = 2;
5343
5344 while (*args[cur_arg]) {
5345 if (!strcmp(args[cur_arg], "users")) {
5346 userlist->groupusers[userlist->grpcnt] = strdup(args[cur_arg + 1]);
5347 cur_arg += 2;
5348 continue;
5349 } else {
5350 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5351 file, linenum, args[0]);
5352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
5354 }
5355 }
5356
5357 userlist->groups[userlist->grpcnt++] = strdup(args[1]);
5358 } else if (!strcmp(args[0], "user")) { /* new user */
5359 struct auth_users *newuser;
5360 int cur_arg;
5361
5362 if (!*args[1]) {
5363 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5364 file, linenum, args[0]);
5365 err_code |= ERR_ALERT | ERR_FATAL;
5366 goto out;
5367 }
5368
5369 for (newuser = userlist->users; newuser; newuser = newuser->next)
5370 if (!strcmp(newuser->user, args[1])) {
5371 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5372 file, linenum, args[1], userlist->name);
5373 err_code |= ERR_ALERT;
5374 goto out;
5375 }
5376
5377 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5378 if (!newuser) {
5379 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5380 err_code |= ERR_ALERT | ERR_ABORT;
5381 goto out;
5382 }
5383
5384 newuser->user = strdup(args[1]);
5385
5386 newuser->next = userlist->users;
5387 userlist->users = newuser;
5388
5389 cur_arg = 2;
5390
5391 while (*args[cur_arg]) {
5392 if (!strcmp(args[cur_arg], "password")) {
5393#ifndef CONFIG_HAP_CRYPT
5394 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5395 file, linenum);
5396 err_code |= ERR_ALERT;
5397#endif
5398 newuser->pass = strdup(args[cur_arg + 1]);
5399 cur_arg += 2;
5400 continue;
5401 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5402 newuser->pass = strdup(args[cur_arg + 1]);
5403 newuser->flags |= AU_O_INSECURE;
5404 cur_arg += 2;
5405 continue;
5406 } else if (!strcmp(args[cur_arg], "groups")) {
Willy Tarreaub4c06b72010-02-02 11:28:20 +01005407 newuser->u.groups = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005408 cur_arg += 2;
5409 continue;
5410 } else {
5411 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5412 file, linenum, args[0]);
5413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
5415 }
5416 }
5417 } else {
5418 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5419 err_code |= ERR_ALERT | ERR_FATAL;
5420 }
5421
5422out:
5423 return err_code;
5424}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425
5426/*
5427 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005428 * Returns the error code, 0 if OK, or any combination of :
5429 * - ERR_ABORT: must abort ASAP
5430 * - ERR_FATAL: we can continue parsing but not start the service
5431 * - ERR_WARN: a warning has been emitted
5432 * - ERR_ALERT: an alert has been emitted
5433 * Only the two first ones can stop processing, the two others are just
5434 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005436int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005437{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005438 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005439 FILE *f;
5440 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005441 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02005442 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005443
Willy Tarreaubaaee002006-06-26 02:48:02 +02005444 if ((f=fopen(file,"r")) == NULL)
5445 return -1;
5446
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005447 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005448 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005449 char *end;
5450 char *args[MAX_LINE_ARGS + 1];
5451 char *line = thisline;
5452
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 linenum++;
5454
5455 end = line + strlen(line);
5456
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005457 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5458 /* Check if we reached the limit and the last char is not \n.
5459 * Watch out for the last line without the terminating '\n'!
5460 */
5461 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005462 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005464 }
5465
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005467 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 line++;
5469
5470 arg = 0;
5471 args[arg] = line;
5472
5473 while (*line && arg < MAX_LINE_ARGS) {
5474 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5475 * C equivalent value. Other combinations left unchanged (eg: \1).
5476 */
5477 if (*line == '\\') {
5478 int skip = 0;
5479 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5480 *line = line[1];
5481 skip = 1;
5482 }
5483 else if (line[1] == 'r') {
5484 *line = '\r';
5485 skip = 1;
5486 }
5487 else if (line[1] == 'n') {
5488 *line = '\n';
5489 skip = 1;
5490 }
5491 else if (line[1] == 't') {
5492 *line = '\t';
5493 skip = 1;
5494 }
5495 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005496 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005497 unsigned char hex1, hex2;
5498 hex1 = toupper(line[2]) - '0';
5499 hex2 = toupper(line[3]) - '0';
5500 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5501 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5502 *line = (hex1<<4) + hex2;
5503 skip = 3;
5504 }
5505 else {
5506 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005507 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005508 }
5509 }
5510 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005511 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005512 end -= skip;
5513 }
5514 line++;
5515 }
5516 else if (*line == '#' || *line == '\n' || *line == '\r') {
5517 /* end of string, end of loop */
5518 *line = 0;
5519 break;
5520 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005521 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005522 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005523 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005524 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005525 line++;
5526 args[++arg] = line;
5527 }
5528 else {
5529 line++;
5530 }
5531 }
5532
5533 /* empty line */
5534 if (!**args)
5535 continue;
5536
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005537 if (*line) {
5538 /* we had to stop due to too many args.
5539 * Let's terminate the string, print the offending part then cut the
5540 * last arg.
5541 */
5542 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5543 line++;
5544 *line = '\0';
5545
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005546 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005547 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005548 err_code |= ERR_ALERT | ERR_FATAL;
5549 args[arg] = line;
5550 }
5551
Willy Tarreau540abe42007-05-02 20:50:16 +02005552 /* zero out remaining args and ensure that at least one entry
5553 * is zeroed out.
5554 */
5555 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005556 args[arg] = line;
5557 }
5558
Willy Tarreau3842f002009-06-14 11:39:52 +02005559 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005560 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005561 char *tmp;
5562
Willy Tarreau3842f002009-06-14 11:39:52 +02005563 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005564 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005565 for (arg=0; *args[arg+1]; arg++)
5566 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005567 *tmp = '\0'; // fix the next arg to \0
5568 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005569 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005570 else if (!strcmp(args[0], "default")) {
5571 kwm = KWM_DEF;
5572 for (arg=0; *args[arg+1]; arg++)
5573 args[arg] = args[arg+1]; // shift args after inversion
5574 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005575
William Lallemand0f99e342011-10-12 17:50:54 +02005576 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5577 strcmp(args[0], "log") != 0) {
5578 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005579 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005580 }
5581
Willy Tarreau977b8e42006-12-29 14:19:17 +01005582 if (!strcmp(args[0], "listen") ||
5583 !strcmp(args[0], "frontend") ||
5584 !strcmp(args[0], "backend") ||
5585 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01005586 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005588 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005589 cursection = strdup(args[0]);
5590 }
5591 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02005593 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005594 cursection = strdup(args[0]);
Emeric Brun32da3c42010-09-23 18:39:19 +02005595 }
5596 else if (!strcmp(args[0], "userlist")) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005597 confsect = CFG_USERLIST;
5598 free(cursection);
5599 cursection = strdup(args[0]);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005600 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005601 else if (!strcmp(args[0], "peers")) {
5602 confsect = CFG_PEERS;
5603 free(cursection);
5604 cursection = strdup(args[0]);
5605 }
5606
Willy Tarreaubaaee002006-06-26 02:48:02 +02005607 /* else it's a section keyword */
5608
5609 switch (confsect) {
5610 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02005611 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 break;
5613 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02005614 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 break;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005616 case CFG_USERLIST:
5617 err_code |= cfg_parse_users(file, linenum, args, kwm);
5618 break;
Emeric Brun32da3c42010-09-23 18:39:19 +02005619 case CFG_PEERS:
5620 err_code |= cfg_parse_peers(file, linenum, args, kwm);
5621 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 default:
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005623 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005625 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005626
5627 if (err_code & ERR_ABORT)
5628 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005629 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005630 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01005631 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005632 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005633 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005634}
5635
Willy Tarreaubb925012009-07-23 13:36:36 +02005636/*
5637 * Returns the error code, 0 if OK, or any combination of :
5638 * - ERR_ABORT: must abort ASAP
5639 * - ERR_FATAL: we can continue parsing but not start the service
5640 * - ERR_WARN: a warning has been emitted
5641 * - ERR_ALERT: an alert has been emitted
5642 * Only the two first ones can stop processing, the two others are just
5643 * indicators.
5644 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005645int check_config_validity()
5646{
5647 int cfgerr = 0;
5648 struct proxy *curproxy = NULL;
5649 struct server *newsrv = NULL;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005650 struct userlist *curuserlist = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02005651 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005652 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653
5654 /*
5655 * Now, check for the integrity of all that we have collected.
5656 */
5657
5658 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02005659 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005660
Willy Tarreau55bc0f82009-03-15 14:51:53 +01005661 /* first, we will invert the proxy list order */
5662 curproxy = NULL;
5663 while (proxy) {
5664 struct proxy *next;
5665
5666 next = proxy->next;
5667 proxy->next = curproxy;
5668 curproxy = proxy;
5669 if (!next)
5670 break;
5671 proxy = next;
5672 }
5673
Willy Tarreaubaaee002006-06-26 02:48:02 +02005674 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005675 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005676 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01005677 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005678 struct tcp_rule *trule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005679 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005680 unsigned int next_id;
5681
5682 if (!curproxy->uuid) {
5683 /* proxy ID not set, use automatic numbering with first
5684 * spare entry starting with next_pxid.
5685 */
5686 next_pxid = get_next_id(&used_proxy_id, next_pxid);
5687 curproxy->conf.id.key = curproxy->uuid = next_pxid;
5688 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005689 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01005690 next_pxid++;
5691
Willy Tarreau55ea7572007-06-17 19:56:27 +02005692
Willy Tarreaubaaee002006-06-26 02:48:02 +02005693 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02005694 /* ensure we don't keep listeners uselessly bound */
5695 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005696 curproxy = curproxy->next;
5697 continue;
5698 }
5699
Willy Tarreauff01a212009-03-15 13:46:16 +01005700 switch (curproxy->mode) {
5701 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005702 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005703 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005704 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
5705 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005706 cfgerr++;
5707 }
5708
5709 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005710 Warning("config : servers will be ignored for %s '%s'.\n",
5711 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01005712 break;
5713
5714 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005715 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01005716 break;
5717
5718 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02005719 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01005720 break;
5721 }
5722
5723 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005724 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
5725 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 cfgerr++;
5727 }
Willy Tarreauff01a212009-03-15 13:46:16 +01005728
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005729 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02005730 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005731 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005732 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
5733 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005734 cfgerr++;
5735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005737 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005738 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
5739 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005740 cfgerr++;
5741 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005742#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02005743 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005744 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
5745 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005746 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005747 }
5748 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02005749 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01005750 /* If no LB algo is set in a backend, and we're not in
5751 * transparent mode, dispatch mode nor proxy mode, we
5752 * want to use balance roundrobin by default.
5753 */
5754 curproxy->lbprm.algo &= ~BE_LB_ALGO;
5755 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 }
5757 }
Willy Tarreau193cf932007-09-17 10:17:23 +02005758
Willy Tarreau1620ec32011-08-06 17:05:02 +02005759 if (curproxy->options & PR_O_DISPATCH)
5760 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
5761 else if (curproxy->options & PR_O_HTTP_PROXY)
5762 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
5763 else if (curproxy->options & PR_O_TRANSP)
5764 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01005765
Willy Tarreau1620ec32011-08-06 17:05:02 +02005766 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
5767 if (curproxy->options & PR_O_DISABLE404) {
5768 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5769 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
5770 err_code |= ERR_WARN;
5771 curproxy->options &= ~PR_O_DISABLE404;
5772 }
5773 if (curproxy->options2 & PR_O2_CHK_SNDST) {
5774 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
5775 "send-state", proxy_type_str(curproxy), curproxy->id);
5776 err_code |= ERR_WARN;
5777 curproxy->options &= ~PR_O2_CHK_SNDST;
5778 }
Willy Tarreauef781042010-01-27 11:53:01 +01005779 }
5780
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005781 /* if a default backend was specified, let's find it */
5782 if (curproxy->defbe.name) {
5783 struct proxy *target;
5784
Alex Williams96532db2009-11-01 21:27:13 -05005785 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005786 if (!target) {
5787 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
5788 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005789 cfgerr++;
5790 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005791 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
5792 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02005793 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005794 } else {
5795 free(curproxy->defbe.name);
5796 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005797 /* we force the backend to be present on at least all of
5798 * the frontend's processes.
5799 */
5800 target->bind_proc = curproxy->bind_proc ?
5801 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreauff678132012-02-13 14:32:34 +01005802
5803 /* Emit a warning if this proxy also has some servers */
5804 if (curproxy->srv) {
5805 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
5806 curproxy->id);
5807 err_code |= ERR_WARN;
5808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 }
5810 }
5811
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005812 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01005813 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
5814 /* map jump target for ACT_SETBE in req_rep chain */
5815 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01005816 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005817 struct proxy *target;
5818
Willy Tarreaua496b602006-12-17 23:15:24 +01005819 if (exp->action != ACT_SETBE)
5820 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005821
Alex Williams96532db2009-11-01 21:27:13 -05005822 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005823 if (!target) {
5824 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
5825 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01005826 cfgerr++;
5827 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005828 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
5829 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01005830 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01005831 } else {
5832 free((void *)exp->replace);
5833 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005834 /* we force the backend to be present on at least all of
5835 * the frontend's processes.
5836 */
5837 target->bind_proc = curproxy->bind_proc ?
5838 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01005839 }
5840 }
5841 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02005842
5843 /* find the target proxy for 'use_backend' rules */
5844 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02005845 struct proxy *target;
5846
Alex Williams96532db2009-11-01 21:27:13 -05005847 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005848
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005849 if (!target) {
5850 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
5851 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005852 cfgerr++;
5853 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01005854 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
5855 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02005856 cfgerr++;
5857 } else {
5858 free((void *)rule->be.name);
5859 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01005860 /* we force the backend to be present on at least all of
5861 * the frontend's processes.
5862 */
5863 target->bind_proc = curproxy->bind_proc ?
5864 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005865 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02005866 }
5867
5868 /* find the target proxy for 'use_backend' rules */
5869 list_for_each_entry(srule, &curproxy->server_rules, list) {
5870 struct server *target = findserver(curproxy, srule->srv.name);
5871
5872 if (!target) {
5873 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
5874 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
5875 cfgerr++;
5876 continue;
5877 }
5878 free((void *)srule->srv.name);
5879 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02005880 }
5881
Emeric Brunb982a3d2010-01-04 15:45:53 +01005882 /* find the target table for 'stick' rules */
5883 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
5884 struct proxy *target;
5885
Emeric Brun1d33b292010-01-04 15:47:17 +01005886 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
5887 if (mrule->flags & STK_IS_STORE)
5888 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5889
Emeric Brunb982a3d2010-01-04 15:45:53 +01005890 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005891 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005892 else
5893 target = curproxy;
5894
5895 if (!target) {
5896 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
5897 curproxy->id, mrule->table.name);
5898 cfgerr++;
5899 }
5900 else if (target->table.size == 0) {
5901 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5902 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5903 cfgerr++;
5904 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005905 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005906 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5907 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5908 cfgerr++;
5909 }
5910 else {
5911 free((void *)mrule->table.name);
5912 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005913 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005914 }
5915 }
5916
5917 /* find the target table for 'store response' rules */
5918 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
5919 struct proxy *target;
5920
Emeric Brun1d33b292010-01-04 15:47:17 +01005921 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
5922
Emeric Brunb982a3d2010-01-04 15:45:53 +01005923 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02005924 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005925 else
5926 target = curproxy;
5927
5928 if (!target) {
5929 Alert("Proxy '%s': unable to find store table '%s'.\n",
5930 curproxy->id, mrule->table.name);
5931 cfgerr++;
5932 }
5933 else if (target->table.size == 0) {
5934 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
5935 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5936 cfgerr++;
5937 }
Willy Tarreauf0b38bf2010-06-06 13:22:23 +02005938 else if (!stktable_compatible_pattern(mrule->expr, target->table.type)) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005939 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
5940 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
5941 cfgerr++;
5942 }
5943 else {
5944 free((void *)mrule->table.name);
5945 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02005946 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01005947 }
5948 }
5949
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005950 /* find the target table for 'tcp-request' layer 4 rules */
5951 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
5952 struct proxy *target;
5953
Willy Tarreau56123282010-08-06 19:06:56 +02005954 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005955 continue;
5956
5957 if (trule->act_prm.trk_ctr.table.n)
5958 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5959 else
5960 target = curproxy;
5961
5962 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02005963 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
5964 curproxy->id, trule->act_prm.trk_ctr.table.n,
5965 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005966 cfgerr++;
5967 }
5968 else if (target->table.size == 0) {
5969 Alert("Proxy '%s': table '%s' used but not configured.\n",
5970 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5971 cfgerr++;
5972 }
5973 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02005974 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005975 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
5976 cfgerr++;
5977 }
5978 else {
5979 free(trule->act_prm.trk_ctr.table.n);
5980 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02005981 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02005982 * to pass a list of counters to track and allocate them right here using
5983 * stktable_alloc_data_type().
5984 */
5985 }
5986 }
5987
Willy Tarreaud1f96522010-08-03 19:34:32 +02005988 /* find the target table for 'tcp-request' layer 6 rules */
5989 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
5990 struct proxy *target;
5991
Willy Tarreau56123282010-08-06 19:06:56 +02005992 if (trule->action != TCP_ACT_TRK_SC1 && trule->action != TCP_ACT_TRK_SC2)
Willy Tarreaud1f96522010-08-03 19:34:32 +02005993 continue;
5994
5995 if (trule->act_prm.trk_ctr.table.n)
5996 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
5997 else
5998 target = curproxy;
5999
6000 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006001 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6002 curproxy->id, trule->act_prm.trk_ctr.table.n,
6003 trule->action == TCP_ACT_TRK_SC1 ? 1 : 2);
Willy Tarreaud1f96522010-08-03 19:34:32 +02006004 cfgerr++;
6005 }
6006 else if (target->table.size == 0) {
6007 Alert("Proxy '%s': table '%s' used but not configured.\n",
6008 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6009 cfgerr++;
6010 }
6011 else if (trule->act_prm.trk_ctr.type != target->table.type) {
Willy Tarreau56123282010-08-06 19:06:56 +02006012 Alert("Proxy '%s': type of tracking key for sticky counter not usable with type of stick-table '%s'.\n",
Willy Tarreaud1f96522010-08-03 19:34:32 +02006013 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6014 cfgerr++;
6015 }
6016 else {
6017 free(trule->act_prm.trk_ctr.table.n);
6018 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006019 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006020 * to pass a list of counters to track and allocate them right here using
6021 * stktable_alloc_data_type().
6022 */
6023 }
6024 }
6025
Emeric Brun32da3c42010-09-23 18:39:19 +02006026 if (curproxy->table.peers.name) {
6027 struct peers *curpeers = peers;
6028
6029 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6030 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6031 free((void *)curproxy->table.peers.name);
6032 curproxy->table.peers.p = peers;
6033 break;
6034 }
6035 }
6036
6037 if (!curpeers) {
6038 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6039 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006040 free((void *)curproxy->table.peers.name);
6041 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006042 cfgerr++;
6043 }
6044 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006045 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6046 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006047 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006048 cfgerr++;
6049 }
6050 }
6051
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006052 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006053 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006054 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6055 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6056 "proxy", curproxy->id);
6057 cfgerr++;
6058 goto out_uri_auth_compat;
6059 }
6060
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006061 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006062 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006063 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006064 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006065
Willy Tarreau95fa4692010-02-01 13:05:50 +01006066 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6067 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006068
6069 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006070 uri_auth_compat_req[i++] = "realm";
6071 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6072 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006073
Willy Tarreau95fa4692010-02-01 13:05:50 +01006074 uri_auth_compat_req[i++] = "unless";
6075 uri_auth_compat_req[i++] = "{";
6076 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6077 uri_auth_compat_req[i++] = "}";
6078 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006079
Willy Tarreauff011f22011-01-06 17:51:27 +01006080 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6081 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006082 cfgerr++;
6083 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006084 }
6085
Willy Tarreauff011f22011-01-06 17:51:27 +01006086 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006087
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006088 if (curproxy->uri_auth->auth_realm) {
6089 free(curproxy->uri_auth->auth_realm);
6090 curproxy->uri_auth->auth_realm = NULL;
6091 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006092
6093 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006094 }
6095out_uri_auth_compat:
6096
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006097 cfgerr += acl_find_targets(curproxy);
6098
Willy Tarreau2738a142006-07-08 17:28:09 +02006099 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006100 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006101 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006102 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006103 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006104 " | While not properly invalid, you will certainly encounter various problems\n"
6105 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006106 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006107 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006108 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006109 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006110
Willy Tarreau1fa31262007-12-03 00:36:16 +01006111 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6112 * We must still support older configurations, so let's find out whether those
6113 * parameters have been set or must be copied from contimeouts.
6114 */
6115 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006116 if (!curproxy->timeout.tarpit ||
6117 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006118 /* tarpit timeout not set. We search in the following order:
6119 * default.tarpit, curr.connect, default.connect.
6120 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006121 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006122 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006123 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006124 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006125 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006126 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006127 }
6128 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006129 (!curproxy->timeout.queue ||
6130 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006131 /* queue timeout not set. We search in the following order:
6132 * default.queue, curr.connect, default.connect.
6133 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006134 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006135 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006136 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006137 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006138 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006139 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006140 }
6141 }
6142
Willy Tarreau1620ec32011-08-06 17:05:02 +02006143 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006144 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6145 curproxy->check_req = (char *)malloc(curproxy->check_len);
6146 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006147 }
6148
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006149 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006150 if (curproxy->nb_req_cap) {
6151 if (curproxy->mode == PR_MODE_HTTP) {
6152 curproxy->req_cap_pool = create_pool("ptrcap",
6153 curproxy->nb_req_cap * sizeof(char *),
6154 MEM_F_SHARED);
6155 } else {
6156 Warning("config : 'capture request header' ignored for %s '%s' as it requires HTTP mode.\n",
6157 proxy_type_str(curproxy), curproxy->id);
6158 err_code |= ERR_WARN;
6159 curproxy->to_log &= ~LW_REQHDR;
6160 curproxy->nb_req_cap = 0;
6161 }
6162 }
6163
6164 if (curproxy->nb_rsp_cap) {
6165 if (curproxy->mode == PR_MODE_HTTP) {
6166 curproxy->rsp_cap_pool = create_pool("ptrcap",
6167 curproxy->nb_rsp_cap * sizeof(char *),
6168 MEM_F_SHARED);
6169 } else {
6170 Warning("config : 'capture response header' ignored for %s '%s' as it requires HTTP mode.\n",
6171 proxy_type_str(curproxy), curproxy->id);
6172 err_code |= ERR_WARN;
6173 curproxy->to_log &= ~LW_REQHDR;
6174 curproxy->nb_rsp_cap = 0;
6175 }
6176 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006177
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 /* first, we will invert the servers list order */
6179 newsrv = NULL;
6180 while (curproxy->srv) {
6181 struct server *next;
6182
6183 next = curproxy->srv->next;
6184 curproxy->srv->next = newsrv;
6185 newsrv = curproxy->srv;
6186 if (!next)
6187 break;
6188 curproxy->srv = next;
6189 }
6190
Willy Tarreaudd701652010-05-25 23:03:02 +02006191 /* assign automatic UIDs to servers which don't have one yet */
6192 next_id = 1;
6193 newsrv = curproxy->srv;
6194 while (newsrv != NULL) {
6195 if (!newsrv->puid) {
6196 /* server ID not set, use automatic numbering with first
6197 * spare entry starting with next_svid.
6198 */
6199 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6200 newsrv->conf.id.key = newsrv->puid = next_id;
6201 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6202 }
6203 next_id++;
6204 newsrv = newsrv->next;
6205 }
6206
Willy Tarreau20697042007-11-15 23:26:18 +01006207 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006208 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209
Willy Tarreau62c3be22012-01-20 13:12:32 +01006210 /*
6211 * If this server supports a maxconn parameter, it needs a dedicated
6212 * tasks to fill the emptied slots when a connection leaves.
6213 * Also, resolve deferred tracking dependency if needed.
6214 */
6215 newsrv = curproxy->srv;
6216 while (newsrv != NULL) {
6217 if (newsrv->minconn > newsrv->maxconn) {
6218 /* Only 'minconn' was specified, or it was higher than or equal
6219 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6220 * this will avoid further useless expensive computations.
6221 */
6222 newsrv->maxconn = newsrv->minconn;
6223 } else if (newsrv->maxconn && !newsrv->minconn) {
6224 /* minconn was not specified, so we set it to maxconn */
6225 newsrv->minconn = newsrv->maxconn;
6226 }
6227
6228 if (newsrv->trackit) {
6229 struct proxy *px;
6230 struct server *srv;
6231 char *pname, *sname;
6232
6233 pname = newsrv->trackit;
6234 sname = strrchr(pname, '/');
6235
6236 if (sname)
6237 *sname++ = '\0';
6238 else {
6239 sname = pname;
6240 pname = NULL;
6241 }
6242
6243 if (pname) {
6244 px = findproxy(pname, PR_CAP_BE);
6245 if (!px) {
6246 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6247 proxy_type_str(curproxy), curproxy->id,
6248 newsrv->id, pname);
6249 cfgerr++;
6250 goto next_srv;
6251 }
6252 } else
6253 px = curproxy;
6254
6255 srv = findserver(px, sname);
6256 if (!srv) {
6257 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6258 proxy_type_str(curproxy), curproxy->id,
6259 newsrv->id, sname);
6260 cfgerr++;
6261 goto next_srv;
6262 }
6263
6264 if (!(srv->state & SRV_CHECKED)) {
6265 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
6266 "tracking as it does not have checks enabled.\n",
6267 proxy_type_str(curproxy), curproxy->id,
6268 newsrv->id, px->id, srv->id);
6269 cfgerr++;
6270 goto next_srv;
6271 }
6272
6273 if (curproxy != px &&
6274 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6275 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6276 "tracking: disable-on-404 option inconsistency.\n",
6277 proxy_type_str(curproxy), curproxy->id,
6278 newsrv->id, px->id, srv->id);
6279 cfgerr++;
6280 goto next_srv;
6281 }
6282
6283 /* if the other server is forced disabled, we have to do the same here */
6284 if (srv->state & SRV_MAINTAIN) {
6285 newsrv->state |= SRV_MAINTAIN;
6286 newsrv->state &= ~SRV_RUNNING;
6287 newsrv->health = 0;
6288 }
6289
6290 newsrv->track = srv;
6291 newsrv->tracknext = srv->tracknext;
6292 srv->tracknext = newsrv;
6293
6294 free(newsrv->trackit);
6295 newsrv->trackit = NULL;
6296 }
6297 next_srv:
6298 newsrv = newsrv->next;
6299 }
6300
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006301 /* We have to initialize the server lookup mechanism depending
6302 * on what LB algorithm was choosen.
6303 */
6304
6305 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6306 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6307 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006308 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6309 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6310 init_server_map(curproxy);
6311 } else {
6312 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6313 fwrr_init_server_groups(curproxy);
6314 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006315 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006316
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006317 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006318 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6319 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6320 fwlc_init_server_tree(curproxy);
6321 } else {
6322 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6323 fas_init_server_tree(curproxy);
6324 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006325 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006326
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006327 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006328 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6329 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6330 chash_init_server_tree(curproxy);
6331 } else {
6332 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6333 init_server_map(curproxy);
6334 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006335 break;
6336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337
6338 if (curproxy->options & PR_O_LOGASAP)
6339 curproxy->to_log &= ~LW_BYTES;
6340
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006341 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
William Lallemand0f99e342011-10-12 17:50:54 +02006342 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006343 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6344 proxy_type_str(curproxy), curproxy->id);
6345 err_code |= ERR_WARN;
6346 }
6347
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006348 if (curproxy->mode != PR_MODE_HTTP) {
6349 int optnum;
6350
6351 if (curproxy->options & PR_O_COOK_ANY) {
6352 Warning("config : 'cookie' statement ignored for %s '%s' as it requires HTTP mode.\n",
6353 proxy_type_str(curproxy), curproxy->id);
6354 err_code |= ERR_WARN;
6355 }
6356
6357 if (curproxy->uri_auth) {
6358 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6359 proxy_type_str(curproxy), curproxy->id);
6360 err_code |= ERR_WARN;
6361 curproxy->uri_auth = NULL;
6362 }
6363
Willy Tarreau87cf5142011-08-19 22:57:24 +02006364 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006365 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6366 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6367 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006368 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006369 }
6370
6371 if (curproxy->options & PR_O_ORGTO) {
6372 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6373 "originalto", proxy_type_str(curproxy), curproxy->id);
6374 err_code |= ERR_WARN;
6375 curproxy->options &= ~PR_O_ORGTO;
6376 }
6377
6378 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6379 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6380 (curproxy->cap & cfg_opts[optnum].cap) &&
6381 (curproxy->options & cfg_opts[optnum].val)) {
6382 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6383 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6384 err_code |= ERR_WARN;
6385 curproxy->options &= ~cfg_opts[optnum].val;
6386 }
6387 }
6388
6389 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6390 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6391 (curproxy->cap & cfg_opts2[optnum].cap) &&
6392 (curproxy->options2 & cfg_opts2[optnum].val)) {
6393 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6394 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6395 err_code |= ERR_WARN;
6396 curproxy->options2 &= ~cfg_opts2[optnum].val;
6397 }
6398 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006399
Willy Tarreauefa5f512010-03-30 20:13:29 +02006400#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006401 if (curproxy->bind_hdr_occ) {
6402 curproxy->bind_hdr_occ = 0;
6403 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
6404 proxy_type_str(curproxy), curproxy->id, curproxy->bind_hdr_name);
6405 err_code |= ERR_WARN;
6406 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006407#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006408 }
6409
Willy Tarreaubaaee002006-06-26 02:48:02 +02006410 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006411 * ensure that we're not cross-dressing a TCP server into HTTP.
6412 */
6413 newsrv = curproxy->srv;
6414 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006415 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006416 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6417 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006418 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006419 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006420
Willy Tarreau0cec3312011-10-31 13:49:26 +01006421 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6422 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6423 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6424 err_code |= ERR_WARN;
6425 }
6426
Willy Tarreauefa5f512010-03-30 20:13:29 +02006427#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaubce70882009-09-07 11:51:47 +02006428 if (curproxy->mode != PR_MODE_HTTP && newsrv->bind_hdr_occ) {
6429 newsrv->bind_hdr_occ = 0;
6430 Warning("config : %s '%s' : server %s cannot use header %s as source IP in non-HTTP mode.\n",
6431 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->bind_hdr_name);
6432 err_code |= ERR_WARN;
6433 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006434#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01006435 newsrv = newsrv->next;
6436 }
6437
Willy Tarreauc1a21672009-08-16 22:37:44 +02006438 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006439 curproxy->accept = frontend_accept;
6440
Willy Tarreauc1a21672009-08-16 22:37:44 +02006441 if (curproxy->tcp_req.inspect_delay ||
6442 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02006443 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006444
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006445 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006446 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006447 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006448 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006449
6450 /* both TCP and HTTP must check switching rules */
6451 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
6452 }
6453
6454 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02006455 if (curproxy->tcp_req.inspect_delay ||
6456 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
6457 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
6458
Emeric Brun97679e72010-09-23 17:56:44 +02006459 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
6460 curproxy->be_rsp_ana |= AN_RES_INSPECT;
6461
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006462 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02006463 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02006464 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02006465 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02006466
6467 /* If the backend does requires RDP cookie persistence, we have to
6468 * enable the corresponding analyser.
6469 */
6470 if (curproxy->options2 & PR_O2_RDPC_PRST)
6471 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
6472 }
6473
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006474 listener = NULL;
6475 while (curproxy->listen) {
6476 struct listener *next;
6477
6478 next = curproxy->listen->next;
6479 curproxy->listen->next = listener;
6480 listener = curproxy->listen;
6481
6482 if (!next)
6483 break;
6484
6485 curproxy->listen = next;
6486 }
6487
Willy Tarreaue6b98942007-10-29 01:09:36 +01006488 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006489 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01006490 listener = curproxy->listen;
6491 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006492 if (!listener->luid) {
6493 /* listener ID not set, use automatic numbering with first
6494 * spare entry starting with next_luid.
6495 */
6496 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
6497 listener->conf.id.key = listener->luid = next_id;
6498 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006499 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006500 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006501
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02006502 /* enable separate counters */
6503 if (curproxy->options2 & PR_O2_SOCKSTAT) {
6504 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
6505 if (!listener->name) {
6506 sprintf(trash, "sock-%d", listener->luid);
6507 listener->name = strdup(trash);
6508 }
6509 }
6510
Willy Tarreaue6b98942007-10-29 01:09:36 +01006511 if (curproxy->options & PR_O_TCP_NOLING)
6512 listener->options |= LI_O_NOLINGER;
6513 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01006514 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006515 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02006516 listener->accept = session_accept;
Willy Tarreaueb472682010-05-28 18:46:57 +02006517 listener->frontend = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006518 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02006519 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01006520
Willy Tarreau8a956912010-10-15 14:27:08 +02006521 if (listener->options & LI_O_ACC_PROXY)
6522 listener->analysers |= AN_REQ_DECODE_PROXY;
6523
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02006524 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
6525 listener->options |= LI_O_TCP_RULES;
6526
Willy Tarreaude3041d2010-05-31 10:56:17 +02006527 if (curproxy->mon_mask.s_addr)
6528 listener->options |= LI_O_CHK_MONNET;
6529
Willy Tarreau9ea05a72009-06-14 12:07:01 +02006530 /* smart accept mode is automatic in HTTP mode */
6531 if ((curproxy->options2 & PR_O2_SMARTACC) ||
6532 (curproxy->mode == PR_MODE_HTTP &&
6533 !(curproxy->no_options2 & PR_O2_SMARTACC)))
6534 listener->options |= LI_O_NOQUICKACK;
6535
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02006536 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01006537 listener = listener->next;
6538 }
6539
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006540 /* Check multi-process mode compatibility for the current proxy */
6541 if (global.nbproc > 1) {
6542 int nbproc = 0;
6543 if (curproxy->bind_proc) {
6544 int proc;
6545 for (proc = 0; proc < global.nbproc; proc++) {
6546 if (curproxy->bind_proc & (1 << proc)) {
6547 nbproc++;
6548 }
6549 }
6550 } else {
6551 nbproc = global.nbproc;
6552 }
6553 if (curproxy->table.peers.name) {
6554 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6555 curproxy->id);
6556 cfgerr++;
6557 }
6558 if (nbproc > 1) {
6559 if (curproxy->uri_auth) {
6560 Warning("Proxy '%s': in multi-process mode, stats will be limited to process assigned to the current request.\n",
6561 curproxy->id);
6562 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
6563 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
6564 curproxy->id);
6565 }
6566 }
6567 if (curproxy->appsession_name) {
6568 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
6569 curproxy->id);
6570 }
6571 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
6572 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
6573 curproxy->id);
6574 }
6575 }
6576 }
Willy Tarreau918ff602011-07-25 16:33:49 +02006577
6578 /* create the task associated with the proxy */
6579 curproxy->task = task_new();
6580 if (curproxy->task) {
6581 curproxy->task->context = curproxy;
6582 curproxy->task->process = manage_proxy;
6583 /* no need to queue, it will be done automatically if some
6584 * listener gets limited.
6585 */
6586 curproxy->task->expire = TICK_ETERNITY;
6587 } else {
6588 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
6589 curproxy->id);
6590 cfgerr++;
6591 }
6592
Willy Tarreaubaaee002006-06-26 02:48:02 +02006593 curproxy = curproxy->next;
6594 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006595
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01006596 /* Check multi-process mode compatibility */
6597 if (global.nbproc > 1) {
6598 if (global.stats_fe) {
6599 Warning("stats socket will not work correctly in multi-process mode (nbproc > 1).\n");
6600 }
6601 }
6602
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006603 for (curuserlist = userlist; curuserlist; curuserlist = curuserlist->next) {
6604 struct auth_users *curuser;
6605 int g;
6606
6607 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6608 unsigned int group_mask = 0;
6609 char *group = NULL;
6610
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006611 if (!curuser->u.groups)
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006612 continue;
6613
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006614 while ((group = strtok(group?NULL:curuser->u.groups, ","))) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006615
6616 for (g = 0; g < curuserlist->grpcnt; g++)
6617 if (!strcmp(curuserlist->groups[g], group))
6618 break;
6619
6620 if (g == curuserlist->grpcnt) {
6621 Alert("userlist '%s': no such group '%s' specified in user '%s'\n",
6622 curuserlist->name, group, curuser->user);
6623 err_code |= ERR_ALERT | ERR_FATAL;
6624 goto out;
6625 }
6626
6627 group_mask |= (1 << g);
6628 }
6629
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006630 free(curuser->u.groups);
6631 curuser->u.group_mask = group_mask;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006632 }
6633
6634 for (g = 0; g < curuserlist->grpcnt; g++) {
6635 char *user = NULL;
6636
6637 if (!curuserlist->groupusers[g])
6638 continue;
6639
6640 while ((user = strtok(user?NULL:curuserlist->groupusers[g], ","))) {
6641 for (curuser = curuserlist->users; curuser; curuser = curuser->next)
6642 if (!strcmp(curuser->user, user))
6643 break;
6644
6645 if (!curuser) {
6646 Alert("userlist '%s': no such user '%s' specified in group '%s'\n",
6647 curuserlist->name, user, curuserlist->groups[g]);
6648 err_code |= ERR_ALERT | ERR_FATAL;
6649 goto out;
6650 }
6651
Willy Tarreaub4c06b72010-02-02 11:28:20 +01006652 curuser->u.group_mask |= (1 << g);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006653 }
6654
6655 free(curuserlist->groupusers[g]);
6656 }
6657
6658 free(curuserlist->groupusers);
6659
6660#ifdef DEBUG_AUTH
6661 for (g = 0; g < curuserlist->grpcnt; g++) {
6662 fprintf(stderr, "group %s, id %d, mask %08X, users:", curuserlist->groups[g], g , 1 << g);
6663
6664 for (curuser = curuserlist->users; curuser; curuser = curuser->next) {
6665 if (curuser->group_mask & (1 << g))
6666 fprintf(stderr, " %s", curuser->user);
6667 }
6668
6669 fprintf(stderr, "\n");
6670 }
6671#endif
6672
Willy Tarreaufbb78422011-06-05 15:38:35 +02006673 }
6674
6675 /* automatically compute fullconn if not set. We must not do it in the
6676 * loop above because cross-references are not yet fully resolved.
6677 */
6678 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
6679 /* If <fullconn> is not set, let's set it to 10% of the sum of
6680 * the possible incoming frontend's maxconns.
6681 */
6682 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
6683 struct proxy *fe;
6684 int total = 0;
6685
6686 /* sum up the number of maxconns of frontends which
6687 * reference this backend at least once or which are
6688 * the same one ('listen').
6689 */
6690 for (fe = proxy; fe; fe = fe->next) {
6691 struct switching_rule *rule;
6692 struct hdr_exp *exp;
6693 int found = 0;
6694
6695 if (!(fe->cap & PR_CAP_FE))
6696 continue;
6697
6698 if (fe == curproxy) /* we're on a "listen" instance */
6699 found = 1;
6700
6701 if (fe->defbe.be == curproxy) /* "default_backend" */
6702 found = 1;
6703
6704 /* check if a "use_backend" rule matches */
6705 if (!found) {
6706 list_for_each_entry(rule, &fe->switching_rules, list) {
6707 if (rule->be.backend == curproxy) {
6708 found = 1;
6709 break;
6710 }
6711 }
6712 }
6713
6714 /* check if a "reqsetbe" rule matches */
6715 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
6716 if (exp->action == ACT_SETBE &&
6717 (struct proxy *)exp->replace == curproxy) {
6718 found = 1;
6719 break;
6720 }
6721 }
6722
6723 /* now we've checked all possible ways to reference a backend
6724 * from a frontend.
6725 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02006726 if (!found)
6727 continue;
6728 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02006729 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02006730 /* we have the sum of the maxconns in <total>. We only
6731 * keep 10% of that sum to set the default fullconn, with
6732 * a hard minimum of 1 (to avoid a divide by zero).
6733 */
6734 curproxy->fullconn = (total + 9) / 10;
6735 if (!curproxy->fullconn)
6736 curproxy->fullconn = 1;
6737 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006738 }
6739
Willy Tarreau056f5682010-06-06 15:51:11 +02006740 /* initialize stick-tables on backend capable proxies. This must not
6741 * be done earlier because the data size may be discovered while parsing
6742 * other proxies.
6743 */
6744 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006745 stktable_init(&curproxy->table);
Willy Tarreau056f5682010-06-06 15:51:11 +02006746
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006747 /*
6748 * Recount currently required checks.
6749 */
6750
6751 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
6752 int optnum;
6753
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006754 for (optnum = 0; cfg_opts[optnum].name; optnum++)
6755 if (curproxy->options & cfg_opts[optnum].val)
6756 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006757
Willy Tarreau66aa61f2009-01-18 21:44:07 +01006758 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
6759 if (curproxy->options2 & cfg_opts2[optnum].val)
6760 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006761 }
6762
Willy Tarreau122541c2011-09-07 21:24:49 +02006763 if (peers) {
6764 struct peers *curpeers = peers, **last;
6765 struct peer *p, *pb;
6766
6767 /* Remove all peers sections which don't have a valid listener.
6768 * This can happen when a peers section is never referenced and
6769 * does not contain a local peer.
6770 */
6771 last = &peers;
6772 while (*last) {
6773 curpeers = *last;
6774 if (curpeers->peers_fe) {
6775 last = &curpeers->next;
6776 continue;
6777 }
6778
6779 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
6780 curpeers->id, localpeer);
6781
6782 p = curpeers->remote;
6783 while (p) {
6784 pb = p->next;
6785 free(p->id);
6786 free(p);
6787 p = pb;
6788 }
6789
6790 /* Destroy and unlink this curpeers section.
6791 * Note: curpeers is backed up into *last.
6792 */
6793 free(curpeers->id);
6794 curpeers = curpeers->next;
6795 free(*last);
6796 *last = curpeers;
6797 }
6798 }
6799
Willy Tarreauac1932d2011-10-24 19:14:41 +02006800 if (!global.tune.max_http_hdr)
6801 global.tune.max_http_hdr = MAX_HTTP_HDR;
6802
Willy Tarreau34eb6712011-10-24 18:15:04 +02006803 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02006804 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02006805 MEM_F_SHARED);
6806
Willy Tarreaubb925012009-07-23 13:36:36 +02006807 if (cfgerr > 0)
6808 err_code |= ERR_ALERT | ERR_FATAL;
6809 out:
6810 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006811}
6812
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006813/*
6814 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
6815 * parsing sessions.
6816 */
6817void cfg_register_keywords(struct cfg_kw_list *kwl)
6818{
6819 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
6820}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006821
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006822/*
6823 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
6824 */
6825void cfg_unregister_keywords(struct cfg_kw_list *kwl)
6826{
6827 LIST_DEL(&kwl->list);
6828 LIST_INIT(&kwl->list);
6829}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006830
6831/*
6832 * Local variables:
6833 * c-indent-level: 8
6834 * c-basic-offset: 8
6835 * End:
6836 */