blob: eea9d3e7d5055d5c3341c1eeda3fa4e6cff84cc5 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004 * Copyright 2000-2010 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>
Willy Tarreaubaaee002006-06-26 02:48:02 +020038
Willy Tarreaueb0c6142007-05-07 00:53:22 +020039#include <proto/acl.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020040#include <proto/backend.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010041#include <proto/buffers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020042#include <proto/checks.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020043#include <proto/dumpstats.h>
Willy Tarreau0f772532006-12-23 20:51:41 +010044#include <proto/httperr.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020045#include <proto/lb_chash.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020046#include <proto/lb_fwlc.h>
47#include <proto/lb_fwrr.h>
48#include <proto/lb_map.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <proto/log.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010050#include <proto/pattern.h>
Willy Tarreauc6f4ce82009-06-10 11:09:37 +020051#include <proto/port_range.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010052#include <proto/protocols.h>
53#include <proto/proto_tcp.h>
54#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010055#include <proto/proxy.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010057#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010059#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020060
61
Willy Tarreauf3c69202006-07-09 16:42:34 +020062/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
63 * ssl-hello-chk option to ensure that the remote server speaks SSL.
64 *
65 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
66 */
67const char sslv3_client_hello_pkt[] = {
68 "\x16" /* ContentType : 0x16 = Hanshake */
69 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
70 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
71 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
72 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
73 "\x03\x00" /* Hello Version : 0x0300 = v3 */
74 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
75 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
76 "\x00" /* Session ID length : empty (no session ID) */
77 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
78 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
79 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
80 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
81 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
82 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
83 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
84 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
85 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
86 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
87 "\x00\x38" "\x00\x39" "\x00\x3A"
88 "\x01" /* Compression Length : 0x01 = 1 byte for types */
89 "\x00" /* Compression Type : 0x00 = NULL compression */
90};
91
Willy Tarreau3842f002009-06-14 11:39:52 +020092/* various keyword modifiers */
93enum kw_mod {
94 KWM_STD = 0, /* normal */
95 KWM_NO, /* "no" prefixed before the keyword */
96 KWM_DEF, /* "default" prefixed before the keyword */
97};
98
Willy Tarreau13943ab2006-12-31 00:24:10 +010099/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100100struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100101 const char *name;
102 unsigned int val;
103 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100104 unsigned int checks;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100105};
106
107/* proxy->options */
108static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100109{
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100110 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100111 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100112 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100113 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100114 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0 },
115 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0 },
Willy Tarreaua31e5df2009-12-30 01:10:35 +0100116 { "forceclose", PR_O_FORCE_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100117 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0 },
118 { "httpclose", PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
119 { "keepalive", PR_O_KEEPALIVE, PR_CAP_NONE, 0 },
Willy Tarreaub608feb2010-01-02 22:47:18 +0100120 { "http-server-close", PR_O_SERVER_CLO, PR_CAP_FE | PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100121 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0 },
122 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100123 { "persist", PR_O_PERSIST, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100124 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0 },
125 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100126#ifdef TPROXY
Willy Tarreau4b1f8592008-12-23 23:13:55 +0100127 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100128#endif
129
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100130 { NULL, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100131};
132
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100133/* proxy->options2 */
134static const struct cfg_opt cfg_opts2[] =
135{
136#ifdef CONFIG_HAP_LINUX_SPLICE
137 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0 },
138 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0 },
139 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0 },
140#endif
Willy Tarreau32a4ec02009-04-02 11:35:18 +0200141 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0 },
142 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0 },
Willy Tarreauc9bd0cc2009-05-10 11:57:02 +0200143 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
144 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0 },
Krzysztof Piotr Oledzki213014e2009-09-27 15:50:02 +0200145 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0 },
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200146 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0 },
Willy Tarreau9ea05a72009-06-14 12:07:01 +0200147 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0 },
Willy Tarreaud88edf22009-06-14 15:48:17 +0200148 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0 },
Willy Tarreauf27b5ea2009-10-03 22:01:18 +0200149 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100150 { NULL, 0, 0, 0 }
151};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200152
Willy Tarreau6daf3432008-01-22 16:44:08 +0100153static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200154static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
155int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100156int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200157
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200158/* List head of all known configuration keywords */
159static struct cfg_kw_list cfg_keywords = {
160 .list = LIST_HEAD_INIT(cfg_keywords.list)
161};
162
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163/*
164 * converts <str> to a list of listeners which are dynamically allocated.
165 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
166 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
167 * - <port> is a numerical port from 1 to 65535 ;
168 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
169 * This can be repeated as many times as necessary, separated by a coma.
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200170 * Function returns 1 for success or 0 if error.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171 */
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200172static int str2listener(char *str, struct proxy *curproxy)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173{
174 struct listener *l;
175 char *c, *next, *range, *dupstr;
176 int port, end;
177
178 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200179
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180 while (next && *next) {
181 struct sockaddr_storage ss;
182
183 str = next;
184 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100185 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 *next++ = 0;
187 }
188
189 /* 2) look for the addr/port delimiter, it's the last colon. */
190 if ((range = strrchr(str, ':')) == NULL) {
191 Alert("Missing port number: '%s'\n", str);
192 goto fail;
193 }
194
195 *range++ = 0;
196
197 if (strrchr(str, ':') != NULL) {
198 /* IPv6 address contains ':' */
199 memset(&ss, 0, sizeof(ss));
200 ss.ss_family = AF_INET6;
201
202 if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in6 *)&ss)->sin6_addr)) {
203 Alert("Invalid server address: '%s'\n", str);
204 goto fail;
205 }
206 }
207 else {
208 memset(&ss, 0, sizeof(ss));
209 ss.ss_family = AF_INET;
210
211 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
212 ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
213 }
214 else if (!inet_pton(ss.ss_family, str, &((struct sockaddr_in *)&ss)->sin_addr)) {
215 struct hostent *he;
216
217 if ((he = gethostbyname(str)) == NULL) {
218 Alert("Invalid server name: '%s'\n", str);
219 goto fail;
220 }
221 else
222 ((struct sockaddr_in *)&ss)->sin_addr =
223 *(struct in_addr *) *(he->h_addr_list);
224 }
225 }
226
227 /* 3) look for the port-end delimiter */
228 if ((c = strchr(range, '-')) != NULL) {
229 *c++ = 0;
230 end = atol(c);
231 }
232 else {
233 end = atol(range);
234 }
235
236 port = atol(range);
237
238 if (port < 1 || port > 65535) {
239 Alert("Invalid port '%d' specified for address '%s'.\n", port, str);
240 goto fail;
241 }
242
243 if (end < 1 || end > 65535) {
244 Alert("Invalid port '%d' specified for address '%s'.\n", end, str);
245 goto fail;
246 }
247
248 for (; port <= end; port++) {
249 l = (struct listener *)calloc(1, sizeof(struct listener));
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200250 l->next = curproxy->listen;
251 curproxy->listen = l;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
253 l->fd = -1;
254 l->addr = ss;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100255 l->state = LI_INIT;
256
257 if (ss.ss_family == AF_INET6) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100259 tcpv6_add_listener(l);
260 } else {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100262 tcpv4_add_listener(l);
263 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200264
Willy Tarreaue6b98942007-10-29 01:09:36 +0100265 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 } /* end for(port) */
267 } /* end while(next) */
268 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200269 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200270 fail:
271 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200272 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200273}
274
Willy Tarreau977b8e42006-12-29 14:19:17 +0100275/*
276 * Sends a warning if proxy <proxy> does not have at least one of the
277 * capabilities in <cap>. An optionnal <hint> may be added at the end
278 * of the warning to help the user. Returns 1 if a warning was emitted
279 * or 0 if the condition is valid.
280 */
281int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, char *arg, char *hint)
282{
283 char *msg;
284
285 switch (cap) {
286 case PR_CAP_BE: msg = "no backend"; break;
287 case PR_CAP_FE: msg = "no frontend"; break;
288 case PR_CAP_RS: msg = "no ruleset"; break;
289 case PR_CAP_BE|PR_CAP_FE: msg = "neither frontend nor backend"; break;
290 default: msg = "not enough"; break;
291 }
292
293 if (!(proxy->cap & cap)) {
294 Warning("parsing [%s:%d] : '%s' ignored because %s '%s' has %s capability.%s\n",
Willy Tarreau2b5652f2006-12-31 17:46:05 +0100295 file, line, arg, proxy_type_str(proxy), proxy->id, msg, hint ? hint : "");
Willy Tarreau977b8e42006-12-29 14:19:17 +0100296 return 1;
297 }
298 return 0;
299}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300
Willy Tarreau61d18892009-03-31 10:49:21 +0200301/* Report a warning if a rule is placed after a 'block' rule.
302 * Return 1 if the warning has been emitted, otherwise 0.
303 */
304int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, char *arg)
305{
306 if (!LIST_ISEMPTY(&proxy->block_cond)) {
307 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
308 file, line, arg);
309 return 1;
310 }
311 return 0;
312}
313
314/* Report a warning if a rule is placed after a reqrewrite rule.
315 * Return 1 if the warning has been emitted, otherwise 0.
316 */
317int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
318{
319 if (proxy->req_exp) {
320 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
321 file, line, arg);
322 return 1;
323 }
324 return 0;
325}
326
327/* Report a warning if a rule is placed after a reqadd rule.
328 * Return 1 if the warning has been emitted, otherwise 0.
329 */
330int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
331{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100332 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200333 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
334 file, line, arg);
335 return 1;
336 }
337 return 0;
338}
339
340/* Report a warning if a rule is placed after a redirect rule.
341 * Return 1 if the warning has been emitted, otherwise 0.
342 */
343int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, char *arg)
344{
345 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
346 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
347 file, line, arg);
348 return 1;
349 }
350 return 0;
351}
352
353/* Report a warning if a rule is placed after a 'use_backend' rule.
354 * Return 1 if the warning has been emitted, otherwise 0.
355 */
356int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, char *arg)
357{
358 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
359 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
360 file, line, arg);
361 return 1;
362 }
363 return 0;
364}
365
366/* report a warning if a block rule is dangerously placed */
367int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, char *arg)
368{
369 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
370 warnif_rule_after_reqadd(proxy, file, line, arg) ||
371 warnif_rule_after_redirect(proxy, file, line, arg) ||
372 warnif_rule_after_use_backend(proxy, file, line, arg);
373}
374
375/* report a warning if a reqxxx rule is dangerously placed */
376int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, char *arg)
377{
378 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
379 warnif_rule_after_redirect(proxy, file, line, arg) ||
380 warnif_rule_after_use_backend(proxy, file, line, arg);
381}
382
383/* report a warning if a reqadd rule is dangerously placed */
384int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, char *arg)
385{
386 return warnif_rule_after_redirect(proxy, file, line, arg) ||
387 warnif_rule_after_use_backend(proxy, file, line, arg);
388}
389
Willy Tarreaubaaee002006-06-26 02:48:02 +0200390/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200391 * parse a line in a <global> section. Returns the error code, 0 if OK, or
392 * any combination of :
393 * - ERR_ABORT: must abort ASAP
394 * - ERR_FATAL: we can continue parsing but not start the service
395 * - ERR_WARN: a warning has been emitted
396 * - ERR_ALERT: an alert has been emitted
397 * Only the two first ones can stop processing, the two others are just
398 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200399 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200400int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200401{
Willy Tarreau058e9072009-07-20 09:30:05 +0200402 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200403
404 if (!strcmp(args[0], "global")) { /* new section */
405 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200406 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200407 }
408 else if (!strcmp(args[0], "daemon")) {
409 global.mode |= MODE_DAEMON;
410 }
411 else if (!strcmp(args[0], "debug")) {
412 global.mode |= MODE_DEBUG;
413 }
414 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100415 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200416 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200417 else if (!strcmp(args[0], "nosepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100418 global.tune.options &= ~GTUNE_USE_SEPOLL;
Willy Tarreaude99e992007-04-16 00:53:59 +0200419 }
420 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100421 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200423 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100424 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200425 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100426 else if (!strcmp(args[0], "nosplice")) {
427 global.tune.options &= ~GTUNE_USE_SPLICE;
428 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200429 else if (!strcmp(args[0], "quiet")) {
430 global.mode |= MODE_QUIET;
431 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200432 else if (!strcmp(args[0], "tune.maxpollevents")) {
433 if (global.tune.maxpollevents != 0) {
434 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200435 err_code |= ERR_ALERT;
436 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200437 }
438 if (*(args[1]) == 0) {
439 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200440 err_code |= ERR_ALERT | ERR_FATAL;
441 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200442 }
443 global.tune.maxpollevents = atol(args[1]);
444 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100445 else if (!strcmp(args[0], "tune.maxaccept")) {
446 if (global.tune.maxaccept != 0) {
447 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200448 err_code |= ERR_ALERT;
449 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100450 }
451 if (*(args[1]) == 0) {
452 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200453 err_code |= ERR_ALERT | ERR_FATAL;
454 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100455 }
456 global.tune.maxaccept = atol(args[1]);
457 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200458 else if (!strcmp(args[0], "tune.bufsize")) {
459 if (*(args[1]) == 0) {
460 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
461 err_code |= ERR_ALERT | ERR_FATAL;
462 goto out;
463 }
464 global.tune.bufsize = atol(args[1]);
465 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
466 global.tune.maxrewrite = global.tune.bufsize / 2;
467 }
468 else if (!strcmp(args[0], "tune.maxrewrite")) {
469 if (*(args[1]) == 0) {
470 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
471 err_code |= ERR_ALERT | ERR_FATAL;
472 goto out;
473 }
474 global.tune.maxrewrite = atol(args[1]);
475 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
476 global.tune.maxrewrite = global.tune.bufsize / 2;
477 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100478 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
479 if (global.tune.client_rcvbuf != 0) {
480 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
481 err_code |= ERR_ALERT;
482 goto out;
483 }
484 if (*(args[1]) == 0) {
485 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
486 err_code |= ERR_ALERT | ERR_FATAL;
487 goto out;
488 }
489 global.tune.client_rcvbuf = atol(args[1]);
490 }
491 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
492 if (global.tune.server_rcvbuf != 0) {
493 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
494 err_code |= ERR_ALERT;
495 goto out;
496 }
497 if (*(args[1]) == 0) {
498 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
499 err_code |= ERR_ALERT | ERR_FATAL;
500 goto out;
501 }
502 global.tune.server_rcvbuf = atol(args[1]);
503 }
504 else if (!strcmp(args[0], "tune.sndbuf.client")) {
505 if (global.tune.client_sndbuf != 0) {
506 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
507 err_code |= ERR_ALERT;
508 goto out;
509 }
510 if (*(args[1]) == 0) {
511 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
512 err_code |= ERR_ALERT | ERR_FATAL;
513 goto out;
514 }
515 global.tune.client_sndbuf = atol(args[1]);
516 }
517 else if (!strcmp(args[0], "tune.sndbuf.server")) {
518 if (global.tune.server_sndbuf != 0) {
519 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
520 err_code |= ERR_ALERT;
521 goto out;
522 }
523 if (*(args[1]) == 0) {
524 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
525 err_code |= ERR_ALERT | ERR_FATAL;
526 goto out;
527 }
528 global.tune.server_sndbuf = atol(args[1]);
529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530 else if (!strcmp(args[0], "uid")) {
531 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200532 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200533 err_code |= ERR_ALERT;
534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200535 }
536 if (*(args[1]) == 0) {
537 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200538 err_code |= ERR_ALERT | ERR_FATAL;
539 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 }
541 global.uid = atol(args[1]);
542 }
543 else if (!strcmp(args[0], "gid")) {
544 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200545 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200546 err_code |= ERR_ALERT;
547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
549 if (*(args[1]) == 0) {
550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200551 err_code |= ERR_ALERT | ERR_FATAL;
552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200553 }
554 global.gid = atol(args[1]);
555 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200556 /* user/group name handling */
557 else if (!strcmp(args[0], "user")) {
558 struct passwd *ha_user;
559 if (global.uid != 0) {
560 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200561 err_code |= ERR_ALERT;
562 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200563 }
564 errno = 0;
565 ha_user = getpwnam(args[1]);
566 if (ha_user != NULL) {
567 global.uid = (int)ha_user->pw_uid;
568 }
569 else {
570 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 +0200571 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200572 }
573 }
574 else if (!strcmp(args[0], "group")) {
575 struct group *ha_group;
576 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200577 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 err_code |= ERR_ALERT;
579 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200580 }
581 errno = 0;
582 ha_group = getgrnam(args[1]);
583 if (ha_group != NULL) {
584 global.gid = (int)ha_group->gr_gid;
585 }
586 else {
587 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 +0200588 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200589 }
590 }
591 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 else if (!strcmp(args[0], "nbproc")) {
593 if (global.nbproc != 0) {
594 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200595 err_code |= ERR_ALERT;
596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 }
598 if (*(args[1]) == 0) {
599 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200600 err_code |= ERR_ALERT | ERR_FATAL;
601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
603 global.nbproc = atol(args[1]);
604 }
605 else if (!strcmp(args[0], "maxconn")) {
606 if (global.maxconn != 0) {
607 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 err_code |= ERR_ALERT;
609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 }
611 if (*(args[1]) == 0) {
612 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200613 err_code |= ERR_ALERT | ERR_FATAL;
614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
616 global.maxconn = atol(args[1]);
617#ifdef SYSTEM_MAXCONN
618 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
619 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);
620 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200621 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 }
623#endif /* SYSTEM_MAXCONN */
624 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100625 else if (!strcmp(args[0], "maxpipes")) {
626 if (global.maxpipes != 0) {
627 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT;
629 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +0100635 }
636 global.maxpipes = atol(args[1]);
637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200638 else if (!strcmp(args[0], "ulimit-n")) {
639 if (global.rlimit_nofile != 0) {
640 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200641 err_code |= ERR_ALERT;
642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 }
644 if (*(args[1]) == 0) {
645 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200646 err_code |= ERR_ALERT | ERR_FATAL;
647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 }
649 global.rlimit_nofile = atol(args[1]);
650 }
651 else if (!strcmp(args[0], "chroot")) {
652 if (global.chroot != NULL) {
653 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200654 err_code |= ERR_ALERT;
655 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
657 if (*(args[1]) == 0) {
658 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200659 err_code |= ERR_ALERT | ERR_FATAL;
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 }
662 global.chroot = strdup(args[1]);
663 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200664 else if (!strcmp(args[0], "description")) {
665 int i, len=0;
666 char *d;
667
668 if (!*args[1]) {
669 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
670 file, linenum, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 for(i=1; *args[i]; i++)
676 len += strlen(args[i])+1;
677
678 if (global.desc)
679 free(global.desc);
680
681 global.desc = d = (char *)calloc(1, len);
682
683 d += sprintf(d, "%s", args[1]);
684 for(i=2; *args[i]; i++)
685 d += sprintf(d, " %s", args[i]);
686 }
687 else if (!strcmp(args[0], "node")) {
688 int i;
689 char c;
690
691 for (i=0; args[1][i]; i++) {
692 c = args[1][i];
693 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
694 break;
695 }
696
697 if (!i || args[1][i]) {
698 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
699 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
700 file, linenum, args[0]);
701 err_code |= ERR_ALERT | ERR_FATAL;
702 goto out;
703 }
704
705 if (global.node)
706 free(global.node);
707
708 global.node = strdup(args[1]);
709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200710 else if (!strcmp(args[0], "pidfile")) {
711 if (global.pidfile != NULL) {
712 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT;
714 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200715 }
716 if (*(args[1]) == 0) {
717 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200718 err_code |= ERR_ALERT | ERR_FATAL;
719 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200720 }
721 global.pidfile = strdup(args[1]);
722 }
723 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +0100724 struct logsrv logsrv;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200725 int facility, level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200726
727 if (*(args[1]) == 0 || *(args[2]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200731 }
732
733 facility = get_log_facility(args[2]);
734 if (facility < 0) {
735 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200736 err_code |= ERR_ALERT | ERR_FATAL;
737 facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200738 }
739
740 level = 7; /* max syslog level = debug */
741 if (*(args[3])) {
742 level = get_log_level(args[3]);
743 if (level < 0) {
744 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200745 err_code |= ERR_ALERT | ERR_FATAL;
746 level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200747 }
748 }
749
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200750 minlvl = 0; /* limit syslog level to this level (emerg) */
751 if (*(args[4])) {
752 minlvl = get_log_level(args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200753 if (minlvl < 0) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200754 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200755 err_code |= ERR_ALERT | ERR_FATAL;
756 minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200757 }
758 }
759
Robert Tsai81ae1952007-12-05 10:47:29 +0100760 if (args[1][0] == '/') {
761 logsrv.u.addr.sa_family = AF_UNIX;
762 logsrv.u.un = *str2sun(args[1]);
763 } else {
764 logsrv.u.addr.sa_family = AF_INET;
765 logsrv.u.in = *str2sa(args[1]);
766 if (!logsrv.u.in.sin_port)
767 logsrv.u.in.sin_port = htons(SYSLOG_PORT);
768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200769
770 if (global.logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100771 global.logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200772 global.logfac1 = facility;
773 global.loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200774 global.minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200775 }
776 else if (global.logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +0100777 global.logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200778 global.logfac2 = facility;
779 global.loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +0200780 global.minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200781 }
782 else {
783 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200784 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200785 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200786 }
787 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
788 if (global.spread_checks != 0) {
789 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200790 err_code |= ERR_ALERT;
791 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200792 }
793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200797 }
798 global.spread_checks = atol(args[1]);
799 if (global.spread_checks < 0 || global.spread_checks > 50) {
800 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200801 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +0200802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200803 }
804 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200805 struct cfg_kw_list *kwl;
806 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200807 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200808
809 list_for_each_entry(kwl, &cfg_keywords.list, list) {
810 for (index = 0; kwl->kw[index].kw != NULL; index++) {
811 if (kwl->kw[index].section != CFG_GLOBAL)
812 continue;
813 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
814 /* prepare error message just in case */
815 snprintf(trash, sizeof(trash),
816 "error near '%s' in '%s' section", args[0], "global");
Willy Tarreau39f23b62008-07-09 20:22:56 +0200817 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, trash, sizeof(trash));
818 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200819 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200820 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200821 }
Willy Tarreau39f23b62008-07-09 20:22:56 +0200822 else if (rc > 0) {
823 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau058e9072009-07-20 09:30:05 +0200824 err_code |= ERR_WARN;
825 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +0200826 }
Willy Tarreau058e9072009-07-20 09:30:05 +0200827 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200828 }
829 }
830 }
831
Willy Tarreaubaaee002006-06-26 02:48:02 +0200832 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +0200833 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200834 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +0200835
Willy Tarreau058e9072009-07-20 09:30:05 +0200836 out:
837 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200838}
839
Willy Tarreau97cb7802010-01-03 20:23:58 +0100840/* Perform the most basic initialization of a proxy :
841 * memset(), list_init(*), reset_timeouts(*).
842 */
843static void init_new_proxy(struct proxy *p)
844{
845 memset(p, 0, sizeof(struct proxy));
846 LIST_INIT(&p->pendconns);
847 LIST_INIT(&p->acl);
848 LIST_INIT(&p->block_cond);
849 LIST_INIT(&p->redirect_rules);
850 LIST_INIT(&p->mon_fail_cond);
851 LIST_INIT(&p->switching_rules);
Willy Tarreau4de91492010-01-22 19:10:05 +0100852 LIST_INIT(&p->force_persist_rules);
Emeric Brunb982a3d2010-01-04 15:45:53 +0100853 LIST_INIT(&p->sticking_rules);
854 LIST_INIT(&p->storersp_rules);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100855 LIST_INIT(&p->tcp_req.inspect_rules);
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100856 LIST_INIT(&p->req_add);
857 LIST_INIT(&p->rsp_add);
Willy Tarreau97cb7802010-01-03 20:23:58 +0100858
859 /* Timeouts are defined as -1 */
860 proxy_reset_timeouts(p);
861}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862
Willy Tarreau915e1eb2009-06-22 15:48:36 +0200863void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864{
Willy Tarreau97cb7802010-01-03 20:23:58 +0100865 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 defproxy.mode = PR_MODE_TCP;
867 defproxy.state = PR_STNEW;
868 defproxy.maxconn = cfg_maxpconn;
869 defproxy.conn_retries = CONN_RETRIES;
870 defproxy.logfac1 = defproxy.logfac2 = -1; /* log disabled */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100871
872 defproxy.defsrv.inter = DEF_CHKINTR;
873 defproxy.defsrv.fastinter = 0;
874 defproxy.defsrv.downinter = 0;
875 defproxy.defsrv.rise = DEF_RISETIME;
876 defproxy.defsrv.fall = DEF_FALLTIME;
877 defproxy.defsrv.check_port = 0;
878 defproxy.defsrv.maxqueue = 0;
879 defproxy.defsrv.minconn = 0;
880 defproxy.defsrv.maxconn = 0;
881 defproxy.defsrv.slowstart = 0;
882 defproxy.defsrv.onerror = DEF_HANA_ONERR;
883 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
884 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885}
886
887/*
Willy Tarreau977b8e42006-12-29 14:19:17 +0100888 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +0200889 * Returns the error code, 0 if OK, or any combination of :
890 * - ERR_ABORT: must abort ASAP
891 * - ERR_FATAL: we can continue parsing but not start the service
892 * - ERR_WARN: a warning has been emitted
893 * - ERR_ALERT: an alert has been emitted
894 * Only the two first ones can stop processing, the two others are just
895 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200897int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898{
899 static struct proxy *curproxy = NULL;
900 struct server *newsrv = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +0200901 const char *err;
Willy Tarreaub3f32f52007-12-02 22:15:14 +0100902 int rc;
903 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +0200904 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905
Willy Tarreau977b8e42006-12-29 14:19:17 +0100906 if (!strcmp(args[0], "listen"))
907 rc = PR_CAP_LISTEN;
908 else if (!strcmp(args[0], "frontend"))
909 rc = PR_CAP_FE | PR_CAP_RS;
910 else if (!strcmp(args[0], "backend"))
911 rc = PR_CAP_BE | PR_CAP_RS;
912 else if (!strcmp(args[0], "ruleset"))
913 rc = PR_CAP_RS;
914 else
915 rc = PR_CAP_NONE;
916
917 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 if (!*args[1]) {
919 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
920 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
921 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +0200922 err_code |= ERR_ALERT | ERR_ABORT;
923 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200925
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100926 err = invalid_char(args[1]);
927 if (err) {
928 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
929 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +0200930 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +0100931 }
932
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200933 for (curproxy = proxy; curproxy != NULL; curproxy = curproxy->next) {
934 /*
935 * If there are two proxies with the same name only following
936 * combinations are allowed:
937 *
938 * listen backend frontend ruleset
939 * listen - - - -
940 * backend - - OK -
941 * frontend - OK - -
942 * ruleset - - - -
943 */
944
945 if (!strcmp(curproxy->id, args[1]) &&
946 (rc!=(PR_CAP_FE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_BE|PR_CAP_RS)) &&
947 (rc!=(PR_CAP_BE|PR_CAP_RS) || curproxy->cap!=(PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +0200948 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
949 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
950 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +0200951 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +0200952 }
953 }
954
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
956 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +0200957 err_code |= ERR_ALERT | ERR_ABORT;
958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100960
Willy Tarreau97cb7802010-01-03 20:23:58 +0100961 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 curproxy->next = proxy;
963 proxy = curproxy;
Willy Tarreau90a570f2009-10-04 20:54:54 +0200964 curproxy->conf.file = file;
965 curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +0200966 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +0100968 curproxy->cap = rc;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969
970 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +0100971 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau90a570f2009-10-04 20:54:54 +0200972 struct listener *new, *last = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200973 if (!str2listener(args[2], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +0200974 err_code |= ERR_FATAL;
975 goto out;
976 }
Willy Tarreau90a570f2009-10-04 20:54:54 +0200977 new = curproxy->listen;
978 while (new != last) {
979 new->conf.file = file;
980 new->conf.line = linenum;
981 new = new->next;
982 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200983 global.maxsock++;
984 }
985
986 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +0100987 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
988
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200990 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100991 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +0200992 curproxy->no_options = defproxy.no_options;
993 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +0100994 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau31682232007-11-29 15:38:04 +0100995 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau7ac51f62007-03-25 16:00:04 +0200996 curproxy->except_net = defproxy.except_net;
997 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +0200998 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +0200999 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001000
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001001 if (defproxy.fwdfor_hdr_len) {
1002 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
1003 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
1004 }
1005
Willy Tarreaub86db342009-11-30 11:50:16 +01001006 if (defproxy.orgto_hdr_len) {
1007 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
1008 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
1009 }
1010
Willy Tarreau977b8e42006-12-29 14:19:17 +01001011 if (curproxy->cap & PR_CAP_FE) {
1012 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01001013 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02001014 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001015
1016 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001017 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
1018 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001019
1020 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
1021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001022
Willy Tarreau977b8e42006-12-29 14:19:17 +01001023 if (curproxy->cap & PR_CAP_BE) {
1024 curproxy->fullconn = defproxy.fullconn;
1025 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001026
Willy Tarreau977b8e42006-12-29 14:19:17 +01001027 if (defproxy.check_req)
1028 curproxy->check_req = strdup(defproxy.check_req);
1029 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001030
Willy Tarreau977b8e42006-12-29 14:19:17 +01001031 if (defproxy.cookie_name)
1032 curproxy->cookie_name = strdup(defproxy.cookie_name);
1033 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001034 if (defproxy.cookie_domain)
1035 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01001036
Emeric Brun647caf12009-06-30 17:57:00 +02001037 if (defproxy.rdp_cookie_name)
1038 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
1039 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
1040
Willy Tarreau01732802007-11-01 22:48:15 +01001041 if (defproxy.url_param_name)
1042 curproxy->url_param_name = strdup(defproxy.url_param_name);
1043 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001044
Benoitaffb4812009-03-25 13:02:10 +01001045 if (defproxy.hh_name)
1046 curproxy->hh_name = strdup(defproxy.hh_name);
1047 curproxy->hh_len = defproxy.hh_len;
1048 curproxy->hh_match_domain = defproxy.hh_match_domain;
1049
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001050 if (defproxy.iface_name)
1051 curproxy->iface_name = strdup(defproxy.iface_name);
1052 curproxy->iface_len = defproxy.iface_len;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001054
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001055 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01001056 if (defproxy.capture_name)
1057 curproxy->capture_name = strdup(defproxy.capture_name);
1058 curproxy->capture_namelen = defproxy.capture_namelen;
1059 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01001060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001061
Willy Tarreau977b8e42006-12-29 14:19:17 +01001062 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001063 curproxy->timeout.client = defproxy.timeout.client;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001064 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01001065 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001066 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001067 curproxy->uri_auth = defproxy.uri_auth;
1068 curproxy->mon_net = defproxy.mon_net;
1069 curproxy->mon_mask = defproxy.mon_mask;
1070 if (defproxy.monitor_uri)
1071 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
1072 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001073 if (defproxy.defbe.name)
1074 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001075 }
1076
1077 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01001078 curproxy->timeout.connect = defproxy.timeout.connect;
1079 curproxy->timeout.server = defproxy.timeout.server;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01001080 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01001081 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01001082 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02001083 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01001084 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001085 curproxy->source_addr = defproxy.source_addr;
1086 }
1087
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 curproxy->mode = defproxy.mode;
1089 curproxy->logfac1 = defproxy.logfac1;
1090 curproxy->logsrv1 = defproxy.logsrv1;
1091 curproxy->loglev1 = defproxy.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001092 curproxy->minlvl1 = defproxy.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093 curproxy->logfac2 = defproxy.logfac2;
1094 curproxy->logsrv2 = defproxy.logsrv2;
1095 curproxy->loglev2 = defproxy.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001096 curproxy->minlvl2 = defproxy.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001098 curproxy->conf.used_listener_id = EB_ROOT;
1099 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001100
Willy Tarreau93893792009-07-23 13:19:11 +02001101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102 }
1103 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
1104 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01001105 /* FIXME-20070101: we should do this too at the end of the
1106 * config parsing to free all default values.
1107 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02001108 free(defproxy.check_req);
1109 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02001110 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001111 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001112 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01001113 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02001114 free(defproxy.capture_name);
1115 free(defproxy.monitor_uri);
1116 free(defproxy.defbe.name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01001117 free(defproxy.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02001118 free(defproxy.fwdfor_hdr_name);
1119 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01001120 free(defproxy.orgto_hdr_name);
1121 defproxy.orgto_hdr_len = 0;
Willy Tarreau0f772532006-12-23 20:51:41 +01001122
Willy Tarreaua534fea2008-08-03 12:19:50 +02001123 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02001124 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01001125
Willy Tarreaubaaee002006-06-26 02:48:02 +02001126 /* we cannot free uri_auth because it might already be used */
1127 init_default_instance();
1128 curproxy = &defproxy;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001129 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02001130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001131 }
1132 else if (curproxy == NULL) {
1133 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001134 err_code |= ERR_ALERT | ERR_FATAL;
1135 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
1137
Willy Tarreau977b8e42006-12-29 14:19:17 +01001138
1139 /* Now let's parse the proxy-specific keywords */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau90a570f2009-10-04 20:54:54 +02001141 struct listener *new_listen, *last_listen;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001142 int cur_arg;
1143
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 if (curproxy == &defproxy) {
1145 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001149 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001150 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151
1152 if (strchr(args[1], ':') == NULL) {
1153 Alert("parsing [%s:%d] : '%s' expects [addr1]:port1[-end1]{,[addr]:port[-end]}... as arguments.\n",
1154 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001158
1159 last_listen = curproxy->listen;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001160 if (!str2listener(args[1], curproxy)) {
Willy Tarreau93893792009-07-23 13:19:11 +02001161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001164
Willy Tarreau90a570f2009-10-04 20:54:54 +02001165 new_listen = curproxy->listen;
1166 while (new_listen != last_listen) {
1167 new_listen->conf.file = file;
1168 new_listen->conf.line = linenum;
1169 new_listen = new_listen->next;
1170 }
1171
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001172 cur_arg = 2;
1173 while (*(args[cur_arg])) {
1174 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
1175#ifdef SO_BINDTODEVICE
1176 struct listener *l;
1177
1178 if (!*args[cur_arg + 1]) {
1179 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
1180 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001183 }
1184
1185 for (l = curproxy->listen; l != last_listen; l = l->next)
1186 l->interface = strdup(args[cur_arg + 1]);
1187
1188 global.last_checks |= LSTCHK_NETADM;
1189
1190 cur_arg += 2;
1191 continue;
1192#else
1193 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1194 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001195 err_code |= ERR_ALERT | ERR_FATAL;
1196 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001197#endif
1198 }
Willy Tarreaube1b9182009-06-14 18:48:19 +02001199 if (!strcmp(args[cur_arg], "mss")) { /* set MSS of listening socket */
1200#ifdef TCP_MAXSEG
1201 struct listener *l;
1202 int mss;
1203
1204 if (!*args[cur_arg + 1]) {
1205 Alert("parsing [%s:%d] : '%s' : missing MSS value.\n",
1206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001209 }
1210
1211 mss = str2uic(args[cur_arg + 1]);
1212 if (mss < 1 || mss > 65535) {
1213 Alert("parsing [%s:%d]: %s expects an MSS value between 1 and 65535.\n",
1214 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001217 }
1218
1219 for (l = curproxy->listen; l != last_listen; l = l->next)
1220 l->maxseg = mss;
1221
1222 cur_arg += 2;
1223 continue;
1224#else
1225 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1226 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001227 err_code |= ERR_ALERT | ERR_FATAL;
1228 goto out;
Willy Tarreaube1b9182009-06-14 18:48:19 +02001229#endif
1230 }
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001231
1232 if (!strcmp(args[cur_arg], "defer-accept")) { /* wait for some data for 1 second max before doing accept */
1233#ifdef TCP_DEFER_ACCEPT
1234 struct listener *l;
1235
1236 for (l = curproxy->listen; l != last_listen; l = l->next)
1237 l->options |= LI_O_DEF_ACCEPT;
1238
1239 cur_arg ++;
1240 continue;
1241#else
1242 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1243 file, linenum, args[0], args[cur_arg]);
1244 err_code |= ERR_ALERT | ERR_FATAL;
1245 goto out;
1246#endif
1247 }
1248
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001249 if (!strcmp(args[cur_arg], "transparent")) { /* transparently bind to these addresses */
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001250#ifdef CONFIG_HAP_LINUX_TPROXY
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001251 struct listener *l;
1252
1253 for (l = curproxy->listen; l != last_listen; l = l->next)
1254 l->options |= LI_O_FOREIGN;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001255
1256 cur_arg ++;
1257 continue;
1258#else
1259 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
1260 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001261 err_code |= ERR_ALERT | ERR_FATAL;
1262 goto out;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01001263#endif
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001264 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001265
1266 if (!strcmp(args[cur_arg], "name")) {
1267 struct listener *l;
1268
1269 for (l = curproxy->listen; l != last_listen; l = l->next)
1270 l->name = strdup(args[cur_arg + 1]);
1271
1272 cur_arg += 2;
1273 continue;
1274 }
1275
1276 if (!strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001277 struct eb32_node *node;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001278 struct listener *l;
1279
1280 if (curproxy->listen->next != last_listen) {
1281 Alert("parsing [%s:%d]: '%s' can be only used with a single socket.\n",
1282 file, linenum, args[cur_arg]);
1283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
1285 }
1286
1287 if (!*args[cur_arg + 1]) {
1288 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1289 file, linenum, args[cur_arg]);
1290 err_code |= ERR_ALERT | ERR_FATAL;
1291 goto out;
1292 }
1293
1294 curproxy->listen->luid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001295 curproxy->listen->conf.id.key = curproxy->listen->luid;
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001296
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001297 if (curproxy->listen->luid <= 0) {
1298 Alert("parsing [%s:%d]: custom id has to be > 0\n",
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001299 file, linenum);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001304 node = eb32_lookup(&curproxy->conf.used_listener_id, curproxy->listen->luid);
1305 if (node) {
1306 l = container_of(node, struct listener, conf.id);
1307 Alert("parsing [%s:%d]: custom id %d for socket '%s' already used at %s:%d.\n",
1308 file, linenum, l->luid, args[1], l->conf.file, l->conf.line);
1309 err_code |= ERR_ALERT | ERR_FATAL;
1310 goto out;
1311 }
1312 eb32_insert(&curproxy->conf.used_listener_id, &curproxy->listen->conf.id);
1313
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02001314 cur_arg += 2;
1315 continue;
1316 }
1317
Willy Tarreaucb6cd432009-10-13 07:34:14 +02001318 Alert("parsing [%s:%d] : '%s' only supports the 'transparent', 'defer-accept', 'name', 'id', 'mss' and 'interface' options.\n",
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001319 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001320 err_code |= ERR_ALERT | ERR_FATAL;
1321 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01001322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 global.maxsock++;
Willy Tarreau93893792009-07-23 13:19:11 +02001324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001325 }
1326 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
1327 if (!*args[1] || !str2net(args[1], &curproxy->mon_net, &curproxy->mon_mask)) {
1328 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
1329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001330 err_code |= ERR_ALERT | ERR_FATAL;
1331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01001333 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001334 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001335
Willy Tarreaubaaee002006-06-26 02:48:02 +02001336 /* flush useless bits */
1337 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02001338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02001340 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001341 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001342 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001343
Willy Tarreau1c47f852006-07-09 08:22:27 +02001344 if (!*args[1]) {
1345 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
1346 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001349 }
1350
Willy Tarreaua534fea2008-08-03 12:19:50 +02001351 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001352 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001353 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01001354 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02001355 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
1356
Willy Tarreau93893792009-07-23 13:19:11 +02001357 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02001358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001359 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
1360 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
1361 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
1362 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
1363 else {
1364 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001365 err_code |= ERR_ALERT | ERR_FATAL;
1366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 }
1368 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001369 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001370 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001371
1372 if (curproxy == &defproxy) {
1373 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
1374 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001377 }
1378
1379 if (!*args[1]) {
1380 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
1381 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001382 err_code |= ERR_ALERT | ERR_FATAL;
1383 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001384 }
1385
1386 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001387 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001388
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001389 if (curproxy->uuid <= 0) {
1390 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001391 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
1393 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001394 }
1395
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02001396 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
1397 if (node) {
1398 struct proxy *target = container_of(node, struct proxy, conf.id);
1399 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
1400 file, linenum, proxy_type_str(curproxy), curproxy->id,
1401 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
1402 err_code |= ERR_ALERT | ERR_FATAL;
1403 goto out;
1404 }
1405 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01001406 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001407 else if (!strcmp(args[0], "description")) {
1408 int i, len=0;
1409 char *d;
1410
1411 if (!*args[1]) {
1412 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1413 file, linenum, args[0]);
1414 return -1;
1415 }
1416
1417 for(i=1; *args[i]; i++)
1418 len += strlen(args[i])+1;
1419
1420 d = (char *)calloc(1, len);
1421 curproxy->desc = d;
1422
1423 d += sprintf(d, "%s", args[1]);
1424 for(i=2; *args[i]; i++)
1425 d += sprintf(d, " %s", args[i]);
1426
1427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001428 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
1429 curproxy->state = PR_STSTOPPED;
1430 }
1431 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
1432 curproxy->state = PR_STNEW;
1433 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001434 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
1435 int cur_arg = 1;
1436 unsigned int set = 0;
1437
1438 while (*args[cur_arg]) {
1439 int u;
1440 if (strcmp(args[cur_arg], "all") == 0) {
1441 set = 0;
1442 break;
1443 }
1444 else if (strcmp(args[cur_arg], "odd") == 0) {
1445 set |= 0x55555555;
1446 }
1447 else if (strcmp(args[cur_arg], "even") == 0) {
1448 set |= 0xAAAAAAAA;
1449 }
1450 else {
1451 u = str2uic(args[cur_arg]);
1452 if (u < 1 || u > 32) {
1453 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or process numbers from 1 to 32.\n",
1454 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001455 err_code |= ERR_ALERT | ERR_FATAL;
1456 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001457 }
1458 if (u > global.nbproc) {
1459 Warning("parsing [%s:%d]: %s references process number higher than global.nbproc.\n",
1460 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001461 err_code |= ERR_WARN;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01001462 }
1463 set |= 1 << (u - 1);
1464 }
1465 cur_arg++;
1466 }
1467 curproxy->bind_proc = set;
1468 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001469 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02001470 if (curproxy == &defproxy) {
1471 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001472 err_code |= ERR_ALERT | ERR_FATAL;
1473 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001474 }
1475
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001476 err = invalid_char(args[1]);
1477 if (err) {
1478 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
1479 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001480 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001481 }
1482
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001483 if (parse_acl((const char **)args + 1, &curproxy->acl) == NULL) {
1484 Alert("parsing [%s:%d] : error detected while parsing ACL '%s'.\n",
1485 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001486 err_code |= ERR_ALERT | ERR_FATAL;
1487 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02001488 }
1489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 else if (!strcmp(args[0], "cookie")) { /* cookie name */
1491 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001492
Willy Tarreau977b8e42006-12-29 14:19:17 +01001493 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001494 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001495
Willy Tarreaubaaee002006-06-26 02:48:02 +02001496 if (*(args[1]) == 0) {
1497 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
1498 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001502
Willy Tarreau4d187ac2009-12-03 23:13:06 +01001503 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001504 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 curproxy->cookie_name = strdup(args[1]);
1506 curproxy->cookie_len = strlen(curproxy->cookie_name);
1507
1508 cur_arg = 2;
1509 while (*(args[cur_arg])) {
1510 if (!strcmp(args[cur_arg], "rewrite")) {
1511 curproxy->options |= PR_O_COOK_RW;
1512 }
1513 else if (!strcmp(args[cur_arg], "indirect")) {
1514 curproxy->options |= PR_O_COOK_IND;
1515 }
1516 else if (!strcmp(args[cur_arg], "insert")) {
1517 curproxy->options |= PR_O_COOK_INS;
1518 }
1519 else if (!strcmp(args[cur_arg], "nocache")) {
1520 curproxy->options |= PR_O_COOK_NOC;
1521 }
1522 else if (!strcmp(args[cur_arg], "postonly")) {
1523 curproxy->options |= PR_O_COOK_POST;
1524 }
1525 else if (!strcmp(args[cur_arg], "prefix")) {
1526 curproxy->options |= PR_O_COOK_PFX;
1527 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001528 else if (!strcmp(args[cur_arg], "domain")) {
1529 if (!*args[cur_arg + 1]) {
1530 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
1531 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001534 }
1535
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001536 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001537 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001538 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
1539 " dots nor does not start with a dot."
1540 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001541 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01001542 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001543 }
1544
1545 err = invalid_domainchar(args[cur_arg + 1]);
1546 if (err) {
1547 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
1548 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001551 }
1552
Willy Tarreau68a897b2009-12-03 23:28:34 +01001553 if (!curproxy->cookie_domain) {
1554 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
1555 } else {
1556 /* one domain was already specified, add another one by
1557 * building the string which will be returned along with
1558 * the cookie.
1559 */
1560 char *new_ptr;
1561 int new_len = strlen(curproxy->cookie_domain) +
1562 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
1563 new_ptr = malloc(new_len);
1564 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
1565 free(curproxy->cookie_domain);
1566 curproxy->cookie_domain = new_ptr;
1567 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001568 cur_arg++;
1569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 else {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02001571 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache' and 'postonly', 'domain' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 }
1576 cur_arg++;
1577 }
1578 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_IND))) {
1579 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1580 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001581 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 }
1583
1584 if (!POWEROF2(curproxy->options & (PR_O_COOK_RW|PR_O_COOK_INS|PR_O_COOK_PFX))) {
1585 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1586 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001587 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 }
1589 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02001590 else if (!strcmp(args[0], "persist")) { /* persist */
1591 if (*(args[1]) == 0) {
1592 Alert("parsing [%s:%d] : missing persist method.\n",
1593 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
1595 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001596 }
1597
1598 if (!strncmp(args[1], "rdp-cookie", 10)) {
1599 curproxy->options2 |= PR_O2_RDPC_PRST;
1600
Emeric Brunb982a3d2010-01-04 15:45:53 +01001601 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02001602 const char *beg, *end;
1603
1604 beg = args[1] + 11;
1605 end = strchr(beg, ')');
1606
1607 if (!end || end == beg) {
1608 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1609 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001610 err_code |= ERR_ALERT | ERR_FATAL;
1611 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001612 }
1613
1614 free(curproxy->rdp_cookie_name);
1615 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1616 curproxy->rdp_cookie_len = end-beg;
1617 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01001618 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02001619 free(curproxy->rdp_cookie_name);
1620 curproxy->rdp_cookie_name = strdup("msts");
1621 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1622 }
1623 else { /* syntax */
1624 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1625 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001626 err_code |= ERR_ALERT | ERR_FATAL;
1627 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001628 }
1629 }
1630 else {
1631 Alert("parsing [%s:%d] : unknown persist method.\n",
1632 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001633 err_code |= ERR_ALERT | ERR_FATAL;
1634 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02001635 }
1636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001637 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001638 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639
Cyril Bonté3b7a3692010-01-10 17:01:47 +01001640 if (curproxy == &defproxy) {
1641 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1642 err_code |= ERR_ALERT | ERR_FATAL;
1643 goto out;
1644 }
1645
Willy Tarreau977b8e42006-12-29 14:19:17 +01001646 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001647 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001648
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001650 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02001651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 }
1655 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02001656 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 curproxy->appsession_name = strdup(args[1]);
1658 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
1659 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001660 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
1661 if (err) {
1662 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
1663 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001664 err_code |= ERR_ALERT | ERR_FATAL;
1665 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001666 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02001667 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02001668
Willy Tarreau51041c72007-09-09 21:56:53 +02001669 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
1670 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001671 err_code |= ERR_ALERT | ERR_ABORT;
1672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001674
1675 cur_arg = 6;
1676 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001677 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1678 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001679 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01001680 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001681 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01001682 } else if (!strcmp(args[cur_arg], "prefix")) {
1683 curproxy->options2 |= PR_O2_AS_PFX;
1684 } else if (!strcmp(args[cur_arg], "mode")) {
1685 if (!*args[cur_arg + 1]) {
1686 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1687 file, linenum, args[0], args[cur_arg]);
1688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
1690 }
1691
1692 cur_arg++;
1693 if (!strcmp(args[cur_arg], "query-string")) {
1694 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1695 curproxy->options2 |= PR_O2_AS_M_QS;
1696 } else if (!strcmp(args[cur_arg], "path-parameters")) {
1697 curproxy->options2 &= ~PR_O2_AS_M_ANY;
1698 curproxy->options2 |= PR_O2_AS_M_PP;
1699 } else {
1700 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
1701 err_code |= ERR_ALERT | ERR_FATAL;
1702 goto out;
1703 }
1704 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02001705 cur_arg++;
1706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 } /* Url App Session */
1708 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02001709 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001710 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001711
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001713 if (*(args[4]) == 0) {
1714 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001716 err_code |= ERR_ALERT | ERR_FATAL;
1717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02001719 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 curproxy->capture_name = strdup(args[2]);
1721 curproxy->capture_namelen = strlen(curproxy->capture_name);
1722 curproxy->capture_len = atol(args[4]);
1723 if (curproxy->capture_len >= CAPTURE_LEN) {
1724 Warning("parsing [%s:%d] : truncating capture length to %d bytes.\n",
1725 file, linenum, CAPTURE_LEN - 1);
Willy Tarreau93893792009-07-23 13:19:11 +02001726 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 curproxy->capture_len = CAPTURE_LEN - 1;
1728 }
1729 curproxy->to_log |= LW_COOKIE;
1730 }
1731 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1732 struct cap_hdr *hdr;
1733
1734 if (curproxy == &defproxy) {
1735 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 +02001736 err_code |= ERR_ALERT | ERR_FATAL;
1737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001738 }
1739
1740 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1741 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1742 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001743 err_code |= ERR_ALERT | ERR_FATAL;
1744 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 }
1746
1747 hdr = calloc(sizeof(struct cap_hdr), 1);
1748 hdr->next = curproxy->req_cap;
1749 hdr->name = strdup(args[3]);
1750 hdr->namelen = strlen(args[3]);
1751 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001752 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 hdr->index = curproxy->nb_req_cap++;
1754 curproxy->req_cap = hdr;
1755 curproxy->to_log |= LW_REQHDR;
1756 }
1757 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1758 struct cap_hdr *hdr;
1759
1760 if (curproxy == &defproxy) {
1761 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 +02001762 err_code |= ERR_ALERT | ERR_FATAL;
1763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 }
1765
1766 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1767 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1768 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 }
1772 hdr = calloc(sizeof(struct cap_hdr), 1);
1773 hdr->next = curproxy->rsp_cap;
1774 hdr->name = strdup(args[3]);
1775 hdr->namelen = strlen(args[3]);
1776 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02001777 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 hdr->index = curproxy->nb_rsp_cap++;
1779 curproxy->rsp_cap = hdr;
1780 curproxy->to_log |= LW_RSPHDR;
1781 }
1782 else {
1783 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1784 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 }
1788 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001789 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001790 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001791 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01001792
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 if (*(args[1]) == 0) {
1794 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1795 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001798 }
1799 curproxy->conn_retries = atol(args[1]);
1800 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001801 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
1802 int pol = ACL_COND_NONE;
1803 struct acl_cond *cond;
1804
Willy Tarreaub099aca2008-10-12 17:26:37 +02001805 if (curproxy == &defproxy) {
1806 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001809 }
1810
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001811 if (!strcmp(args[1], "if"))
1812 pol = ACL_COND_IF;
1813 else if (!strcmp(args[1], "unless"))
1814 pol = ACL_COND_UNLESS;
1815
1816 if (pol == ACL_COND_NONE) {
1817 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1818 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001819 err_code |= ERR_ALERT | ERR_FATAL;
1820 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001821 }
1822
1823 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
1824 Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
1825 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001826 err_code |= ERR_ALERT | ERR_FATAL;
1827 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001828 }
Willy Tarreau88922352009-10-04 22:02:50 +02001829 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02001830 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02001831 curproxy->acl_requires |= cond->requires;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001832 LIST_ADDQ(&curproxy->block_cond, &cond->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001833 warnif_misplaced_block(curproxy, file, linenum, args[0]);
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02001834 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001835 else if (!strcmp(args[0], "redirect")) {
1836 int pol = ACL_COND_NONE;
Willy Tarreauf285f542010-01-03 20:03:03 +01001837 struct acl_cond *cond = NULL;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001838 struct redirect_rule *rule;
1839 int cur_arg;
1840 int type = REDIRECT_TYPE_NONE;
1841 int code = 302;
1842 char *destination = NULL;
Willy Tarreau0140f252008-11-19 21:07:09 +01001843 char *cookie = NULL;
1844 int cookie_set = 0;
Willy Tarreau79da4692008-11-19 20:03:04 +01001845 unsigned int flags = REDIRECT_FLAG_NONE;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001846
1847 cur_arg = 1;
1848 while (*(args[cur_arg])) {
1849 if (!strcmp(args[cur_arg], "location")) {
1850 if (!*args[cur_arg + 1]) {
1851 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1852 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001853 err_code |= ERR_ALERT | ERR_FATAL;
1854 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001855 }
1856
1857 type = REDIRECT_TYPE_LOCATION;
1858 cur_arg++;
1859 destination = args[cur_arg];
1860 }
1861 else if (!strcmp(args[cur_arg], "prefix")) {
1862 if (!*args[cur_arg + 1]) {
1863 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1864 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001865 err_code |= ERR_ALERT | ERR_FATAL;
1866 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001867 }
1868
1869 type = REDIRECT_TYPE_PREFIX;
1870 cur_arg++;
1871 destination = args[cur_arg];
1872 }
Willy Tarreau0140f252008-11-19 21:07:09 +01001873 else if (!strcmp(args[cur_arg], "set-cookie")) {
1874 if (!*args[cur_arg + 1]) {
1875 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1876 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001877 err_code |= ERR_ALERT | ERR_FATAL;
1878 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001879 }
1880
1881 cur_arg++;
1882 cookie = args[cur_arg];
1883 cookie_set = 1;
1884 }
1885 else if (!strcmp(args[cur_arg], "clear-cookie")) {
1886 if (!*args[cur_arg + 1]) {
1887 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
1888 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
Willy Tarreau0140f252008-11-19 21:07:09 +01001891 }
1892
1893 cur_arg++;
1894 cookie = args[cur_arg];
1895 cookie_set = 0;
1896 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001897 else if (!strcmp(args[cur_arg],"code")) {
1898 if (!*args[cur_arg + 1]) {
1899 Alert("parsing [%s:%d] : '%s': missing HTTP code.\n",
1900 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001903 }
1904 cur_arg++;
1905 code = atol(args[cur_arg]);
1906 if (code < 301 || code > 303) {
1907 Alert("parsing [%s:%d] : '%s': unsupported HTTP code '%d'.\n",
1908 file, linenum, args[0], code);
Willy Tarreau93893792009-07-23 13:19:11 +02001909 err_code |= ERR_ALERT | ERR_FATAL;
1910 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001911 }
1912 }
Willy Tarreau79da4692008-11-19 20:03:04 +01001913 else if (!strcmp(args[cur_arg],"drop-query")) {
1914 flags |= REDIRECT_FLAG_DROP_QS;
1915 }
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001916 else if (!strcmp(args[cur_arg],"append-slash")) {
1917 flags |= REDIRECT_FLAG_APPEND_SLASH;
1918 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001919 else if (!strcmp(args[cur_arg], "if")) {
1920 pol = ACL_COND_IF;
1921 cur_arg++;
1922 break;
1923 }
1924 else if (!strcmp(args[cur_arg], "unless")) {
1925 pol = ACL_COND_UNLESS;
1926 cur_arg++;
1927 break;
1928 }
1929 else {
Willy Tarreau81e3b4f2010-01-10 00:42:19 +01001930 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 +02001931 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02001932 err_code |= ERR_ALERT | ERR_FATAL;
1933 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001934 }
1935 cur_arg++;
1936 }
1937
1938 if (type == REDIRECT_TYPE_NONE) {
1939 Alert("parsing [%s:%d] : '%s' expects a redirection type ('prefix' or 'location').\n",
1940 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001943 }
1944
Willy Tarreauf285f542010-01-03 20:03:03 +01001945 if (pol != ACL_COND_NONE &&
1946 (cond = parse_acl_cond((const char **)args + cur_arg, &curproxy->acl, pol)) == NULL) {
Jeffrey 'jf' Limaf403fc2009-04-02 21:53:56 +08001947 Alert("parsing [%s:%d] : '%s': error detected while parsing redirect condition.\n",
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001948 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001949 err_code |= ERR_ALERT | ERR_FATAL;
1950 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001951 }
1952
Willy Tarreauf285f542010-01-03 20:03:03 +01001953 if (cond) {
1954 cond->file = file;
1955 cond->line = linenum;
1956 curproxy->acl_requires |= cond->requires;
1957 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001958 rule = (struct redirect_rule *)calloc(1, sizeof(*rule));
1959 rule->cond = cond;
1960 rule->rdr_str = strdup(destination);
1961 rule->rdr_len = strlen(destination);
Willy Tarreau0140f252008-11-19 21:07:09 +01001962 if (cookie) {
1963 /* depending on cookie_set, either we want to set the cookie, or to clear it.
1964 * a clear consists in appending "; Max-Age=0" at the end.
1965 */
1966 rule->cookie_len = strlen(cookie);
1967 if (cookie_set)
1968 rule->cookie_str = strdup(cookie);
1969 else {
1970 rule->cookie_str = malloc(rule->cookie_len + 12);
1971 memcpy(rule->cookie_str, cookie, rule->cookie_len);
1972 memcpy(rule->cookie_str + rule->cookie_len, "; Max-Age=0", 12);
1973 rule->cookie_len += 11;
1974 }
1975 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001976 rule->type = type;
1977 rule->code = code;
Willy Tarreau79da4692008-11-19 20:03:04 +01001978 rule->flags = flags;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001979 LIST_INIT(&rule->list);
1980 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02001981 warnif_rule_after_use_backend(curproxy, file, linenum, args[0]);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02001982 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01001983 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02001984 int pol = ACL_COND_NONE;
1985 struct acl_cond *cond;
1986 struct switching_rule *rule;
1987
Willy Tarreaub099aca2008-10-12 17:26:37 +02001988 if (curproxy == &defproxy) {
1989 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001990 err_code |= ERR_ALERT | ERR_FATAL;
1991 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02001992 }
1993
Willy Tarreau55ea7572007-06-17 19:56:27 +02001994 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02001995 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02001996
1997 if (*(args[1]) == 0) {
1998 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001999 err_code |= ERR_ALERT | ERR_FATAL;
2000 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002001 }
2002
2003 if (!strcmp(args[2], "if"))
2004 pol = ACL_COND_IF;
2005 else if (!strcmp(args[2], "unless"))
2006 pol = ACL_COND_UNLESS;
2007
2008 if (pol == ACL_COND_NONE) {
2009 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2010 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002013 }
2014
2015 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
Willy Tarreaua9802632008-07-25 19:13:19 +02002016 Alert("parsing [%s:%d] : error detected while parsing switching rule.\n",
Willy Tarreau55ea7572007-06-17 19:56:27 +02002017 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
2019 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02002020 }
2021
Willy Tarreau88922352009-10-04 22:02:50 +02002022 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002023 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002024 curproxy->acl_requires |= cond->requires;
Willy Tarreaua9802632008-07-25 19:13:19 +02002025 if (cond->requires & ACL_USE_RTR_ANY) {
Willy Tarreaudd64f8d2008-07-27 22:02:32 +02002026 struct acl *acl;
2027 const char *name;
2028
2029 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2030 name = acl ? acl->name : "(unknown)";
2031 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
2032 file, linenum, name);
Willy Tarreau93893792009-07-23 13:19:11 +02002033 err_code |= ERR_WARN;
Willy Tarreaua9802632008-07-25 19:13:19 +02002034 }
2035
Willy Tarreau55ea7572007-06-17 19:56:27 +02002036 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
2037 rule->cond = cond;
2038 rule->be.name = strdup(args[1]);
2039 LIST_INIT(&rule->list);
2040 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
2041 }
Willy Tarreau4de91492010-01-22 19:10:05 +01002042 else if (!strcmp(args[0], "force-persist")) {
2043 int pol = ACL_COND_NONE;
2044 struct acl_cond *cond;
2045 struct force_persist_rule *rule;
2046
2047 if (curproxy == &defproxy) {
2048 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2049 err_code |= ERR_ALERT | ERR_FATAL;
2050 goto out;
2051 }
2052
2053 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
2054 err_code |= ERR_WARN;
2055
2056 if (!strcmp(args[1], "if"))
2057 pol = ACL_COND_IF;
2058 else if (!strcmp(args[1], "unless"))
2059 pol = ACL_COND_UNLESS;
2060
2061 if (pol == ACL_COND_NONE) {
2062 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
2063 file, linenum, args[0]);
2064 err_code |= ERR_ALERT | ERR_FATAL;
2065 goto out;
2066 }
2067
2068 if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
2069 Alert("parsing [%s:%d] : error detected while parsing a 'force-persist' rule.\n",
2070 file, linenum);
2071 err_code |= ERR_ALERT | ERR_FATAL;
2072 goto out;
2073 }
2074
2075 cond->file = file;
2076 cond->line = linenum;
2077 curproxy->acl_requires |= cond->requires;
2078 if (cond->requires & ACL_USE_RTR_ANY) {
2079 struct acl *acl;
2080 const char *name;
2081
2082 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2083 name = acl ? acl->name : "(unknown)";
2084 Warning("parsing [%s:%d] : acl '%s' involves some response-only criteria which will be ignored.\n",
2085 file, linenum, name);
2086 err_code |= ERR_WARN;
2087 }
2088
2089 rule = (struct force_persist_rule *)calloc(1, sizeof(*rule));
2090 rule->cond = cond;
2091 LIST_INIT(&rule->list);
2092 LIST_ADDQ(&curproxy->force_persist_rules, &rule->list);
2093 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002094 else if (!strcmp(args[0], "stick-table")) {
2095 int myidx = 1;
2096
2097 curproxy->table.type = (unsigned int)-1;
2098 while (*args[myidx]) {
2099 const char *err;
2100
2101 if (strcmp(args[myidx], "size") == 0) {
2102 myidx++;
2103 if (!*(args[myidx])) {
2104 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2105 file, linenum, args[myidx-1]);
2106 err_code |= ERR_ALERT | ERR_FATAL;
2107 goto out;
2108 }
2109 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
2110 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2111 file, linenum, *err, args[myidx-1]);
2112 err_code |= ERR_ALERT | ERR_FATAL;
2113 goto out;
2114 }
2115 }
2116 else if (strcmp(args[myidx], "expire") == 0) {
2117 myidx++;
2118 if (!*(args[myidx])) {
2119 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
2120 file, linenum, args[myidx-1]);
2121 err_code |= ERR_ALERT | ERR_FATAL;
2122 goto out;
2123 }
2124 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
2125 if (err) {
2126 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
2127 file, linenum, *err, args[myidx-1]);
2128 err_code |= ERR_ALERT | ERR_FATAL;
2129 goto out;
2130 }
2131 curproxy->table.expire = val;
2132 }
2133 else if (strcmp(args[myidx], "nopurge") == 0) {
2134 curproxy->table.nopurge = 1;
2135 }
2136 else if (strcmp(args[myidx], "type") == 0) {
2137 myidx++;
2138 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
2139 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
2140 file, linenum, args[myidx]);
2141 err_code |= ERR_ALERT | ERR_FATAL;
2142 goto out;
2143 }
2144 }
2145 myidx++;
2146 }
2147
2148 if (!curproxy->table.size) {
2149 Alert("parsing [%s:%d] : stick-table: missing size.\n",
2150 file, linenum);
2151 err_code |= ERR_ALERT | ERR_FATAL;
2152 goto out;
2153 }
2154
2155 if (curproxy->table.type == (unsigned int)-1) {
2156 Alert("parsing [%s:%d] : stick-table: missing type.\n",
2157 file, linenum);
2158 err_code |= ERR_ALERT | ERR_FATAL;
2159 goto out;
2160 }
2161 }
2162 else if (!strcmp(args[0], "stick")) {
2163 int pol = ACL_COND_NONE;
2164 struct acl_cond *cond = NULL;
2165 struct sticking_rule *rule;
2166 struct pattern_expr *expr;
2167 int myidx = 0;
2168 const char *name = NULL;
2169 int flags;
2170
2171 if (curproxy == &defproxy) {
2172 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2173 err_code |= ERR_ALERT | ERR_FATAL;
2174 goto out;
2175 }
2176
2177 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
2178 err_code |= ERR_WARN;
2179 goto out;
2180 }
2181
2182 myidx++;
2183 if ((strcmp(args[myidx], "store") == 0) ||
2184 (strcmp(args[myidx], "store-request") == 0)) {
2185 myidx++;
2186 flags = STK_IS_STORE;
2187 }
2188 else if (strcmp(args[myidx], "store-response") == 0) {
2189 myidx++;
2190 flags = STK_IS_STORE | STK_ON_RSP;
2191 }
2192 else if (strcmp(args[myidx], "match") == 0) {
2193 myidx++;
2194 flags = STK_IS_MATCH;
2195 }
2196 else if (strcmp(args[myidx], "on") == 0) {
2197 myidx++;
2198 flags = STK_IS_MATCH | STK_IS_STORE;
2199 }
2200 else {
2201 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
2202 err_code |= ERR_ALERT | ERR_FATAL;
2203 goto out;
2204 }
2205
2206 if (*(args[myidx]) == 0) {
2207 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
2208 err_code |= ERR_ALERT | ERR_FATAL;
2209 goto out;
2210 }
2211
2212 expr = pattern_parse_expr(args, &myidx);
2213 if (!expr) {
2214 Alert("parsing [%s:%d] : '%s': unknown fetch method '%s'.\n", file, linenum, args[0], args[myidx]);
2215 err_code |= ERR_ALERT | ERR_FATAL;
2216 goto out;
2217 }
2218
2219 if (flags & STK_ON_RSP) {
2220 if (!(expr->fetch->dir & PATTERN_FETCH_RTR)) {
2221 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on response.\n",
2222 file, linenum, args[0], expr->fetch->kw);
2223 err_code |= ERR_ALERT | ERR_FATAL;
2224 goto out;
2225 }
2226 } else {
2227 if (!(expr->fetch->dir & PATTERN_FETCH_REQ)) {
2228 Alert("parsing [%s:%d] : '%s': fetch method '%s' can not be used on request.\n",
2229 file, linenum, args[0], expr->fetch->kw);
2230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
2232 }
2233 }
2234
2235 if (strcmp(args[myidx], "table") == 0) {
2236 myidx++;
2237 name = args[myidx++];
2238 }
2239
2240 if (*(args[myidx]) == 0)
2241 pol = ACL_COND_NONE;
2242 else if (strcmp(args[myidx], "if") == 0)
2243 pol = ACL_COND_IF;
2244 else if (strcmp(args[myidx], "unless") == 0)
2245 pol = ACL_COND_UNLESS;
2246 else {
2247 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
2248 file, linenum, args[0], args[myidx]);
2249 err_code |= ERR_ALERT | ERR_FATAL;
2250 goto out;
2251 }
2252
2253 if (pol != ACL_COND_NONE) {
2254 myidx++;
2255 if ((cond = parse_acl_cond((const char **)args + myidx, &curproxy->acl, pol)) == NULL) {
2256 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition.\n",
2257 file, linenum, args[0]);
2258 err_code |= ERR_ALERT | ERR_FATAL;
2259 goto out;
2260 }
2261
2262 cond->file = file;
2263 cond->line = linenum;
2264 curproxy->acl_requires |= cond->requires;
2265 if (cond->requires & ACL_USE_RTR_ANY) {
2266 struct acl *acl;
2267 const char *name;
2268
2269 acl = cond_find_require(cond, ACL_USE_RTR_ANY);
2270 name = acl ? acl->name : "(unknown)";
2271 Warning("parsing [%s:%d] : '%s' : acl '%s' involves some response-only criteria which will be ignored.\n",
2272 file, linenum, args[0], name);
2273 err_code |= ERR_WARN;
2274 }
2275 }
2276 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
2277 rule->cond = cond;
2278 rule->expr = expr;
2279 rule->flags = flags;
2280 rule->table.name = name ? strdup(name) : NULL;
2281 LIST_INIT(&rule->list);
2282 if (flags & STK_ON_RSP)
2283 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
2284 else
2285 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
2286 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002287 else if (!strcmp(args[0], "stats")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002288 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002289 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002290
Willy Tarreaubaaee002006-06-26 02:48:02 +02002291 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
2292 curproxy->uri_auth = NULL; /* we must detach from the default config */
2293
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002294 if (!*args[1]) {
2295 goto stats_error_parsing;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 } else if (!strcmp(args[1], "uri")) {
2297 if (*(args[2]) == 0) {
2298 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
2302 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002303 err_code |= ERR_ALERT | ERR_ABORT;
2304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
2306 } else if (!strcmp(args[1], "realm")) {
2307 if (*(args[2]) == 0) {
2308 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002309 err_code |= ERR_ALERT | ERR_FATAL;
2310 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
2312 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002313 err_code |= ERR_ALERT | ERR_ABORT;
2314 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02002316 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002317 unsigned interval;
2318
2319 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
2320 if (err) {
2321 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
2322 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002323 err_code |= ERR_ALERT | ERR_FATAL;
2324 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002325 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
2326 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002327 err_code |= ERR_ALERT | ERR_ABORT;
2328 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02002329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 } else if (!strcmp(args[1], "auth")) {
2331 if (*(args[2]) == 0) {
2332 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002333 err_code |= ERR_ALERT | ERR_FATAL;
2334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
2336 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002337 err_code |= ERR_ALERT | ERR_ABORT;
2338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 }
2340 } else if (!strcmp(args[1], "scope")) {
2341 if (*(args[2]) == 0) {
2342 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002343 err_code |= ERR_ALERT | ERR_FATAL;
2344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
2346 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002347 err_code |= ERR_ALERT | ERR_ABORT;
2348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349 }
2350 } else if (!strcmp(args[1], "enable")) {
2351 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
2352 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_ABORT;
2354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002356 } else if (!strcmp(args[1], "hide-version")) {
2357 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
2358 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002359 err_code |= ERR_ALERT | ERR_ABORT;
2360 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02002361 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01002362 } else if (!strcmp(args[1], "show-legends")) {
2363 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
2364 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2365 err_code |= ERR_ALERT | ERR_ABORT;
2366 goto out;
2367 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002368 } else if (!strcmp(args[1], "show-node")) {
2369
2370 if (*args[2]) {
2371 int i;
2372 char c;
2373
2374 for (i=0; args[2][i]; i++) {
2375 c = args[2][i];
Krzysztof Piotr Oledzki619caca2009-10-03 15:46:08 +02002376 if (!isupper(c) && !islower(c) && !isdigit(c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002377 break;
2378 }
2379
2380 if (!i || args[2][i]) {
2381 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
2382 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
2383 file, linenum, args[0], args[1]);
2384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
2386 }
2387 }
2388
2389 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
2390 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2391 err_code |= ERR_ALERT | ERR_ABORT;
2392 goto out;
2393 }
2394 } else if (!strcmp(args[1], "show-desc")) {
2395 char *desc = NULL;
2396
2397 if (*args[2]) {
2398 int i, len=0;
2399 char *d;
2400
2401 for(i=2; *args[i]; i++)
2402 len += strlen(args[i])+1;
2403
2404 desc = d = (char *)calloc(1, len);
2405
2406 d += sprintf(d, "%s", args[2]);
2407 for(i=3; *args[i]; i++)
2408 d += sprintf(d, " %s", args[i]);
2409 }
2410
2411 if (!*args[2] && !global.desc)
2412 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
2413 file, linenum, args[1]);
2414 else {
2415 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
2416 free(desc);
2417 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
2418 err_code |= ERR_ALERT | ERR_ABORT;
2419 goto out;
2420 }
2421 free(desc);
2422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01002424stats_error_parsing:
2425 Alert("parsing [%s:%d]: %s '%s', expects 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
2426 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
2430 }
2431 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002432 int optnum;
2433
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002434 if (*(args[1]) == '\0') {
2435 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
2436 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002439 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01002440
2441 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
2442 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002443 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2444 err_code |= ERR_WARN;
2445 goto out;
2446 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002447
Willy Tarreau3842f002009-06-14 11:39:52 +02002448 curproxy->no_options &= ~cfg_opts[optnum].val;
2449 curproxy->options &= ~cfg_opts[optnum].val;
2450
2451 switch (kwm) {
2452 case KWM_STD:
2453 curproxy->options |= cfg_opts[optnum].val;
2454 break;
2455 case KWM_NO:
2456 curproxy->no_options |= cfg_opts[optnum].val;
2457 break;
2458 case KWM_DEF: /* already cleared */
2459 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002460 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002461
Willy Tarreau93893792009-07-23 13:19:11 +02002462 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002463 }
2464 }
2465
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002466 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2467 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Willy Tarreau93893792009-07-23 13:19:11 +02002468 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2469 err_code |= ERR_WARN;
2470 goto out;
2471 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002472
Willy Tarreau3842f002009-06-14 11:39:52 +02002473 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2474 curproxy->options2 &= ~cfg_opts2[optnum].val;
2475
2476 switch (kwm) {
2477 case KWM_STD:
2478 curproxy->options2 |= cfg_opts2[optnum].val;
2479 break;
2480 case KWM_NO:
2481 curproxy->no_options2 |= cfg_opts2[optnum].val;
2482 break;
2483 case KWM_DEF: /* already cleared */
2484 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002485 }
Willy Tarreau93893792009-07-23 13:19:11 +02002486 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002487 }
2488 }
2489
Willy Tarreau3842f002009-06-14 11:39:52 +02002490 if (kwm != KWM_STD) {
2491 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002492 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002493 err_code |= ERR_ALERT | ERR_FATAL;
2494 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002495 }
2496
Emeric Brun3a058f32009-06-30 18:26:00 +02002497 if (!strcmp(args[1], "httplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 /* generate a complete HTTP log */
Emeric Brun3a058f32009-06-30 18:26:00 +02002499 curproxy->options2 &= ~PR_O2_CLFLOG;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_REQ | LW_PXID | LW_RESP | LW_BYTES;
Emeric Brun3a058f32009-06-30 18:26:00 +02002501 if (*(args[2]) != '\0') {
2502 if (!strcmp(args[2], "clf")) {
2503 curproxy->options2 |= PR_O2_CLFLOG;
2504 } else {
2505 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02002508 }
2509 }
2510 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002511 else if (!strcmp(args[1], "tcplog"))
2512 /* generate a detailed TCP log */
2513 curproxy->to_log |= LW_DATE | LW_CLIP | LW_SVID | LW_PXID | LW_BYTES;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514 else if (!strcmp(args[1], "tcpka")) {
2515 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002516 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002518
2519 if (curproxy->cap & PR_CAP_FE)
2520 curproxy->options |= PR_O_TCP_CLI_KA;
2521 if (curproxy->cap & PR_CAP_BE)
2522 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002523 }
2524 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01002525 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002526 err_code |= ERR_WARN;
2527
Willy Tarreaubaaee002006-06-26 02:48:02 +02002528 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002529 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002530 curproxy->options &= ~PR_O_SSL3_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002531 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002532 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002533 curproxy->options |= PR_O_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 if (!*args[2]) { /* no argument */
2535 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
2536 curproxy->check_len = strlen(DEF_CHECK_REQ);
2537 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreau23677902007-05-08 23:50:35 +02002538 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539 curproxy->check_req = (char *)malloc(reqlen);
2540 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2541 "OPTIONS %s HTTP/1.0\r\n\r\n", args[2]); /* URI to use */
2542 } else { /* more arguments : METHOD URI [HTTP_VER] */
2543 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n\r\n");
2544 if (*args[4])
2545 reqlen += strlen(args[4]);
2546 else
2547 reqlen += strlen("HTTP/1.0");
2548
2549 curproxy->check_req = (char *)malloc(reqlen);
2550 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2551 "%s %s %s\r\n\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
2552 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02002553 }
2554 else if (!strcmp(args[1], "ssl-hello-chk")) {
2555 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01002556 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002557 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01002558
Willy Tarreaua534fea2008-08-03 12:19:50 +02002559 free(curproxy->check_req);
Willy Tarreauf3c69202006-07-09 16:42:34 +02002560 curproxy->options &= ~PR_O_HTTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002561 curproxy->options &= ~PR_O_SMTP_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002562 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreauf3c69202006-07-09 16:42:34 +02002563 curproxy->options |= PR_O_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
Willy Tarreau23677902007-05-08 23:50:35 +02002565 else if (!strcmp(args[1], "smtpchk")) {
2566 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002567 free(curproxy->check_req);
Willy Tarreau23677902007-05-08 23:50:35 +02002568 curproxy->options &= ~PR_O_HTTP_CHK;
2569 curproxy->options &= ~PR_O_SSL3_CHK;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002570 curproxy->options2 &= ~PR_O2_MYSQL_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02002571 curproxy->options |= PR_O_SMTP_CHK;
2572
2573 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
2574 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2575 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2576 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
2577 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
2578 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
2579 curproxy->check_req = (char *)malloc(reqlen);
2580 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
2581 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
2582 } else {
2583 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
2584 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
2585 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
2586 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
2587 }
2588 }
2589 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01002590 else if (!strcmp(args[1], "mysql-check")) {
2591 /* use MYSQL request to check servers' health */
2592 free(curproxy->check_req);
2593 curproxy->options &= ~PR_O_HTTP_CHK;
2594 curproxy->options &= ~PR_O_SSL3_CHK;
2595 curproxy->options &= ~PR_O_SMTP_CHK;
2596 curproxy->options2 |= PR_O2_MYSQL_CHK;
2597 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002598 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02002599 int cur_arg;
2600
2601 /* insert x-forwarded-for field, but not for the IP address listed as an except.
2602 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002603 */
Ross Westaf72a1d2008-08-03 10:51:45 +02002604
2605 curproxy->options |= PR_O_FWDFOR;
2606
2607 free(curproxy->fwdfor_hdr_name);
2608 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2609 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2610
2611 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2612 cur_arg = 2;
2613 while (*(args[cur_arg])) {
2614 if (!strcmp(args[cur_arg], "except")) {
2615 /* suboption except - needs additional argument for it */
2616 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_net, &curproxy->except_mask)) {
2617 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2618 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002619 err_code |= ERR_ALERT | ERR_FATAL;
2620 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002621 }
2622 /* flush useless bits */
2623 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02002624 cur_arg += 2;
2625 } else if (!strcmp(args[cur_arg], "header")) {
2626 /* suboption header - needs additional argument for it */
2627 if (*(args[cur_arg+1]) == 0) {
2628 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2629 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02002632 }
2633 free(curproxy->fwdfor_hdr_name);
2634 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2635 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2636 cur_arg += 2;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002637 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02002638 /* unknown suboption - catchall */
2639 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2640 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002641 err_code |= ERR_ALERT | ERR_FATAL;
2642 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002643 }
Ross Westaf72a1d2008-08-03 10:51:45 +02002644 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002645 }
Maik Broemme2850cb42009-04-17 18:53:21 +02002646 else if (!strcmp(args[1], "originalto")) {
2647 int cur_arg;
2648
2649 /* insert x-original-to field, but not for the IP address listed as an except.
2650 * set default options (ie: bitfield, header name, etc)
2651 */
2652
2653 curproxy->options |= PR_O_ORGTO;
2654
2655 free(curproxy->orgto_hdr_name);
2656 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2657 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2658
2659 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2660 cur_arg = 2;
2661 while (*(args[cur_arg])) {
2662 if (!strcmp(args[cur_arg], "except")) {
2663 /* suboption except - needs additional argument for it */
2664 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], &curproxy->except_to, &curproxy->except_mask_to)) {
2665 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2666 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002667 err_code |= ERR_ALERT | ERR_FATAL;
2668 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002669 }
2670 /* flush useless bits */
2671 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2672 cur_arg += 2;
2673 } else if (!strcmp(args[cur_arg], "header")) {
2674 /* suboption header - needs additional argument for it */
2675 if (*(args[cur_arg+1]) == 0) {
2676 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2677 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
2679 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002680 }
2681 free(curproxy->orgto_hdr_name);
2682 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2683 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2684 cur_arg += 2;
2685 } else {
2686 /* unknown suboption - catchall */
2687 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2688 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002689 err_code |= ERR_ALERT | ERR_FATAL;
2690 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02002691 }
2692 } /* end while loop */
2693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 else {
2695 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 }
Willy Tarreau93893792009-07-23 13:19:11 +02002699 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002701 else if (!strcmp(args[0], "default_backend")) {
2702 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002703 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002704
2705 if (*(args[1]) == 0) {
2706 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002707 err_code |= ERR_ALERT | ERR_FATAL;
2708 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002709 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002710 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002711 curproxy->defbe.name = strdup(args[1]);
2712 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002713 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002716
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01002717 Warning("parsing [%s:%d]: keyword '%s' is deprecated, please use 'option redispatch' instead.\n",
2718 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 /* enable reconnections to dispatch */
2721 curproxy->options |= PR_O_REDISP;
2722 }
Willy Tarreau48494c02007-11-30 10:41:39 +01002723 else if (!strcmp(args[0], "http-check")) {
2724 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002725 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01002726
2727 if (strcmp(args[1], "disable-on-404") == 0) {
2728 /* enable a graceful server shutdown on an HTTP 404 response */
2729 curproxy->options |= PR_O_DISABLE404;
2730 }
2731 else {
2732 Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_ALERT | ERR_FATAL;
2734 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01002735 }
2736 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01002737 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02002738 if (curproxy == &defproxy) {
2739 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002742 }
2743
Willy Tarreaub80c2302007-11-30 20:51:32 +01002744 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002745 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002746
2747 if (strcmp(args[1], "fail") == 0) {
2748 /* add a condition to fail monitor requests */
2749 int pol = ACL_COND_NONE;
2750 struct acl_cond *cond;
2751
2752 if (!strcmp(args[2], "if"))
2753 pol = ACL_COND_IF;
2754 else if (!strcmp(args[2], "unless"))
2755 pol = ACL_COND_UNLESS;
2756
2757 if (pol == ACL_COND_NONE) {
2758 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2759 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002760 err_code |= ERR_ALERT | ERR_FATAL;
2761 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002762 }
2763
2764 if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
2765 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
2766 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002769 }
Willy Tarreau88922352009-10-04 22:02:50 +02002770 cond->file = file;
Willy Tarreaua9802632008-07-25 19:13:19 +02002771 cond->line = linenum;
Willy Tarreaua9fb0832009-07-10 20:53:53 +02002772 curproxy->acl_requires |= cond->requires;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002773 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2774 }
2775 else {
2776 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01002779 }
2780 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781#ifdef TPROXY
2782 else if (!strcmp(args[0], "transparent")) {
2783 /* enable transparent proxy connections */
2784 curproxy->options |= PR_O_TRANSP;
2785 }
2786#endif
2787 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002788 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002790
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 if (*(args[1]) == 0) {
2792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002793 err_code |= ERR_ALERT | ERR_FATAL;
2794 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 }
2796 curproxy->maxconn = atol(args[1]);
2797 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002798 else if (!strcmp(args[0], "backlog")) { /* backlog */
2799 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002801
2802 if (*(args[1]) == 0) {
2803 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002806 }
2807 curproxy->backlog = atol(args[1]);
2808 }
Willy Tarreau86034312006-12-29 00:10:33 +01002809 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002810 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002812
Willy Tarreau86034312006-12-29 00:10:33 +01002813 if (*(args[1]) == 0) {
2814 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002815 err_code |= ERR_ALERT | ERR_FATAL;
2816 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01002817 }
2818 curproxy->fullconn = atol(args[1]);
2819 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002820 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2821 if (*(args[1]) == 0) {
2822 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002823 err_code |= ERR_ALERT | ERR_FATAL;
2824 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002826 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
2827 if (err) {
2828 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2829 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002832 }
2833 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002834 }
2835 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2836 if (curproxy == &defproxy) {
2837 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002841 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002843
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 if (strchr(args[1], ':') == NULL) {
2845 Alert("parsing [%s:%d] : '%s' expects <addr:port> as argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848 }
2849 curproxy->dispatch_addr = *str2sa(args[1]);
2850 }
2851 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002852 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002853 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854
Jeffrey 'jf' Lim65cb2f12008-10-04 18:07:00 +02002855 memcpy(trash, "error near 'balance'", 21);
Willy Tarreaua0cbda62007-11-01 21:39:54 +01002856 if (backend_parse_balance((const char **)args + 1, trash, sizeof(trash), curproxy) < 0) {
2857 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02002858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02002860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02002862 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2864 err_code |= ERR_WARN;
2865
2866 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2867 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2868 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2869 }
2870 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2871 curproxy->lbprm.algo &= ~BE_LB_HASH_TYPE;
2872 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2873 }
2874 else {
2875 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002880 else if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) { /* server address */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 int cur_arg;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002882 char *rport, *raddr;
2883 short realport = 0;
2884 int do_check = 0, defsrv = (*args[0] == 'd');
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002886 if (!defsrv && curproxy == &defproxy) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002891 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002892 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893
2894 if (!*args[2]) {
2895 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2896 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002897 err_code |= ERR_ALERT | ERR_FATAL;
2898 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 }
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002900
2901 err = invalid_char(args[1]);
2902 if (err) {
2903 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2904 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002905 err_code |= ERR_ALERT | ERR_FATAL;
2906 goto out;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002907 }
2908
Willy Tarreaubaaee002006-06-26 02:48:02 +02002909 if ((newsrv = (struct server *)calloc(1, sizeof(struct server))) == NULL) {
2910 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002911 err_code |= ERR_ALERT | ERR_ABORT;
2912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002913 }
2914
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002915 if (!defsrv) {
2916 /* the servers are linked backwards first */
2917 newsrv->next = curproxy->srv;
2918 curproxy->srv = newsrv;
2919 newsrv->proxy = curproxy;
2920 newsrv->conf.file = file;
2921 newsrv->conf.line = linenum;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002923 LIST_INIT(&newsrv->pendconns);
2924 do_check = 0;
2925 newsrv->state = SRV_RUNNING; /* early server setup */
2926 newsrv->last_change = now.tv_sec;
2927 newsrv->id = strdup(args[1]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002929 /* several ways to check the port component :
2930 * - IP => port=+0, relative
2931 * - IP: => port=+0, relative
2932 * - IP:N => port=N, absolute
2933 * - IP:+N => port=+N, relative
2934 * - IP:-N => port=-N, relative
2935 */
2936 raddr = strdup(args[2]);
2937 rport = strchr(raddr, ':');
2938 if (rport) {
2939 *rport++ = 0;
2940 realport = atol(rport);
2941 if (!isdigit((unsigned char)*rport))
2942 newsrv->state |= SRV_MAPPORTS;
2943 } else
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 newsrv->state |= SRV_MAPPORTS;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002945
2946 newsrv->addr = *str2sa(raddr);
2947 newsrv->addr.sin_port = htons(realport);
2948 free(raddr);
2949
2950 newsrv->check_port = curproxy->defsrv.check_port;
2951 newsrv->inter = curproxy->defsrv.inter;
2952 newsrv->fastinter = curproxy->defsrv.fastinter;
2953 newsrv->downinter = curproxy->defsrv.downinter;
2954 newsrv->rise = curproxy->defsrv.rise;
2955 newsrv->fall = curproxy->defsrv.fall;
2956 newsrv->maxqueue = curproxy->defsrv.maxqueue;
2957 newsrv->minconn = curproxy->defsrv.minconn;
2958 newsrv->maxconn = curproxy->defsrv.maxconn;
2959 newsrv->slowstart = curproxy->defsrv.slowstart;
2960 newsrv->onerror = curproxy->defsrv.onerror;
2961 newsrv->consecutive_errors_limit
2962 = curproxy->defsrv.consecutive_errors_limit;
2963 newsrv->uweight = newsrv->iweight
2964 = curproxy->defsrv.iweight;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002966 newsrv->curfd = -1; /* no health-check in progress */
2967 newsrv->health = newsrv->rise; /* up, but will fall down at first failure */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002968
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002969 cur_arg = 3;
2970 } else {
2971 newsrv = &curproxy->defsrv;
2972 cur_arg = 1;
2973 }
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02002974
Willy Tarreaubaaee002006-06-26 02:48:02 +02002975 while (*args[cur_arg]) {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002976 if (!defsrv && !strcmp(args[cur_arg], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002977 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002978
2979 if (!*args[cur_arg + 1]) {
2980 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2981 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002982 err_code |= ERR_ALERT | ERR_FATAL;
2983 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002984 }
2985
2986 newsrv->puid = atol(args[cur_arg + 1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002987 newsrv->conf.id.key = newsrv->puid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002988
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002989 if (newsrv->puid <= 0) {
2990 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002991 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002992 err_code |= ERR_ALERT | ERR_FATAL;
2993 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002994 }
2995
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002996 node = eb32_lookup(&curproxy->conf.used_server_id, newsrv->puid);
2997 if (node) {
2998 struct server *target = container_of(node, struct server, conf.id);
2999 Alert("parsing [%s:%d]: server %s reuses same custom id as server %s (declared at %s:%d).\n",
3000 file, linenum, newsrv->id, target->id, target->conf.file, target->conf.line);
3001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
3003 }
3004 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003005 cur_arg += 2;
3006 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003007 else if (!defsrv && !strcmp(args[cur_arg], "cookie")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 newsrv->cookie = strdup(args[cur_arg + 1]);
3009 newsrv->cklen = strlen(args[cur_arg + 1]);
3010 cur_arg += 2;
3011 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003012 else if (!defsrv && !strcmp(args[cur_arg], "redir")) {
Willy Tarreau21d2af32008-02-14 20:25:24 +01003013 newsrv->rdr_pfx = strdup(args[cur_arg + 1]);
3014 newsrv->rdr_len = strlen(args[cur_arg + 1]);
3015 cur_arg += 2;
3016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 else if (!strcmp(args[cur_arg], "rise")) {
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003018 if (!*args[cur_arg + 1]) {
3019 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3020 file, linenum, args[cur_arg]);
3021 err_code |= ERR_ALERT | ERR_FATAL;
3022 goto out;
3023 }
3024
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 newsrv->rise = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003026 if (newsrv->rise <= 0) {
3027 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3028 file, linenum, args[cur_arg]);
3029 err_code |= ERR_ALERT | ERR_FATAL;
3030 goto out;
3031 }
3032
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 newsrv->health = newsrv->rise;
3034 cur_arg += 2;
3035 }
3036 else if (!strcmp(args[cur_arg], "fall")) {
3037 newsrv->fall = atol(args[cur_arg + 1]);
Krzysztof Piotr Oledzki08ff9592009-09-27 16:17:31 +02003038
3039 if (!*args[cur_arg + 1]) {
3040 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3041 file, linenum, args[cur_arg]);
3042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
3044 }
3045
3046 if (newsrv->fall <= 0) {
3047 Alert("parsing [%s:%d]: '%s' has to be > 0.\n",
3048 file, linenum, args[cur_arg]);
3049 err_code |= ERR_ALERT | ERR_FATAL;
3050 goto out;
3051 }
3052
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 cur_arg += 2;
3054 }
3055 else if (!strcmp(args[cur_arg], "inter")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003056 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3057 if (err) {
3058 Alert("parsing [%s:%d] : unexpected character '%c' in 'inter' argument of server %s.\n",
3059 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003060 err_code |= ERR_ALERT | ERR_FATAL;
3061 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003062 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003063 if (val <= 0) {
3064 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3065 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003068 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003069 newsrv->inter = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 cur_arg += 2;
3071 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003072 else if (!strcmp(args[cur_arg], "fastinter")) {
3073 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3074 if (err) {
3075 Alert("parsing [%s:%d]: unexpected character '%c' in 'fastinter' argument of server %s.\n",
3076 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003077 err_code |= ERR_ALERT | ERR_FATAL;
3078 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003079 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003080 if (val <= 0) {
3081 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3082 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003083 err_code |= ERR_ALERT | ERR_FATAL;
3084 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003085 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003086 newsrv->fastinter = val;
3087 cur_arg += 2;
3088 }
3089 else if (!strcmp(args[cur_arg], "downinter")) {
3090 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
3091 if (err) {
3092 Alert("parsing [%s:%d]: unexpected character '%c' in 'downinter' argument of server %s.\n",
3093 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003096 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003097 if (val <= 0) {
3098 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3099 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003102 }
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01003103 newsrv->downinter = val;
3104 cur_arg += 2;
3105 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003106 else if (!defsrv && !strcmp(args[cur_arg], "addr")) {
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003107 newsrv->check_addr = *str2sa(args[cur_arg + 1]);
Willy Tarreau2ea3abb2007-03-25 16:45:16 +02003108 cur_arg += 2;
3109 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 else if (!strcmp(args[cur_arg], "port")) {
3111 newsrv->check_port = atol(args[cur_arg + 1]);
3112 cur_arg += 2;
3113 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003114 else if (!defsrv && !strcmp(args[cur_arg], "backup")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 newsrv->state |= SRV_BACKUP;
3116 cur_arg ++;
3117 }
3118 else if (!strcmp(args[cur_arg], "weight")) {
3119 int w;
3120 w = atol(args[cur_arg + 1]);
Willy Tarreau6704d672009-06-15 10:56:05 +02003121 if (w < 0 || w > 256) {
3122 Alert("parsing [%s:%d] : weight of server %s is not within 0 and 256 (%d).\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003123 file, linenum, newsrv->id, w);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
Willy Tarreau975c50b2009-10-10 19:34:06 +02003127 newsrv->uweight = newsrv->iweight = w;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 cur_arg += 2;
3129 }
3130 else if (!strcmp(args[cur_arg], "minconn")) {
3131 newsrv->minconn = atol(args[cur_arg + 1]);
3132 cur_arg += 2;
3133 }
3134 else if (!strcmp(args[cur_arg], "maxconn")) {
3135 newsrv->maxconn = atol(args[cur_arg + 1]);
3136 cur_arg += 2;
3137 }
Elijah Epifanovacafc5f2007-10-25 20:15:38 +02003138 else if (!strcmp(args[cur_arg], "maxqueue")) {
3139 newsrv->maxqueue = atol(args[cur_arg + 1]);
3140 cur_arg += 2;
3141 }
Willy Tarreau9909fc12007-11-30 17:42:05 +01003142 else if (!strcmp(args[cur_arg], "slowstart")) {
3143 /* slowstart is stored in seconds */
Willy Tarreau3259e332007-12-03 01:51:45 +01003144 const char *err = parse_time_err(args[cur_arg + 1], &val, TIME_UNIT_MS);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003145 if (err) {
3146 Alert("parsing [%s:%d] : unexpected character '%c' in 'slowstart' argument of server %s.\n",
3147 file, linenum, *err, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003148 err_code |= ERR_ALERT | ERR_FATAL;
3149 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003150 }
Willy Tarreaue3838802009-03-21 18:58:32 +01003151 if (val <= 0) {
3152 Alert("parsing [%s:%d]: invalid value %d for argument '%s' of server %s.\n",
3153 file, linenum, val, args[cur_arg], newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
Willy Tarreaue3838802009-03-21 18:58:32 +01003156 }
Willy Tarreau3259e332007-12-03 01:51:45 +01003157 newsrv->slowstart = (val + 999) / 1000;
Willy Tarreau9909fc12007-11-30 17:42:05 +01003158 cur_arg += 2;
3159 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003160 else if (!defsrv && !strcmp(args[cur_arg], "track")) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003161
3162 if (!*args[cur_arg + 1]) {
3163 Alert("parsing [%s:%d]: 'track' expects [<proxy>/]<server> as argument.\n",
3164 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003167 }
3168
3169 newsrv->trackit = strdup(args[cur_arg + 1]);
3170
3171 cur_arg += 2;
3172 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003173 else if (!defsrv && !strcmp(args[cur_arg], "check")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003174 global.maxsock++;
3175 do_check = 1;
3176 cur_arg += 1;
3177 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003178 else if (!defsrv && !strcmp(args[cur_arg], "observe")) {
Krzysztof Piotr Oledzki97f07b82009-12-15 22:31:24 +01003179 if (!strcmp(args[cur_arg + 1], "none"))
3180 newsrv->observe = HANA_OBS_NONE;
3181 else if (!strcmp(args[cur_arg + 1], "layer4"))
3182 newsrv->observe = HANA_OBS_LAYER4;
3183 else if (!strcmp(args[cur_arg + 1], "layer7")) {
3184 if (curproxy->mode != PR_MODE_HTTP) {
3185 Alert("parsing [%s:%d]: '%s' can only be used in http proxies.\n",
3186 file, linenum, args[cur_arg + 1]);
3187 err_code |= ERR_ALERT;
3188 }
3189 newsrv->observe = HANA_OBS_LAYER7;
3190 }
3191 else {
3192 Alert("parsing [%s:%d]: '%s' expects one of 'none', "
3193 "'l4events', 'http-responses' but get '%s'\n",
3194 file, linenum, args[cur_arg], args[cur_arg + 1]);
3195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
3197 }
3198
3199 cur_arg += 2;
3200 }
3201 else if (!strcmp(args[cur_arg], "on-error")) {
3202 if (!strcmp(args[cur_arg + 1], "fastinter"))
3203 newsrv->onerror = HANA_ONERR_FASTINTER;
3204 else if (!strcmp(args[cur_arg + 1], "fail-check"))
3205 newsrv->onerror = HANA_ONERR_FAILCHK;
3206 else if (!strcmp(args[cur_arg + 1], "sudden-death"))
3207 newsrv->onerror = HANA_ONERR_SUDDTH;
3208 else if (!strcmp(args[cur_arg + 1], "mark-down"))
3209 newsrv->onerror = HANA_ONERR_MARKDWN;
3210 else {
3211 Alert("parsing [%s:%d]: '%s' expects one of 'fastinter', "
3212 "'fail-check', 'sudden-death' or 'mark-down' but get '%s'\n",
3213 file, linenum, args[cur_arg], args[cur_arg + 1]);
3214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
3216 }
3217
3218 cur_arg += 2;
3219 }
3220 else if (!strcmp(args[cur_arg], "error-limit")) {
3221 if (!*args[cur_arg + 1]) {
3222 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3223 file, linenum, args[cur_arg]);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
3227
3228 newsrv->consecutive_errors_limit = atoi(args[cur_arg + 1]);
3229
3230 if (newsrv->consecutive_errors_limit <= 0) {
3231 Alert("parsing [%s:%d]: %s has to be > 0.\n",
3232 file, linenum, args[cur_arg]);
3233 err_code |= ERR_ALERT | ERR_FATAL;
3234 goto out;
3235 }
3236 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003237 else if (!defsrv && !strcmp(args[cur_arg], "source")) { /* address to which we bind when connecting */
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003238 int port_low, port_high;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 if (!*args[cur_arg + 1]) {
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003240#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003241 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]], and optional '%s' <addr> as argument.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003242 file, linenum, "source", "usesrc");
3243#else
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003244 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>[-<port>]] as argument.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 file, linenum, "source");
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003246#endif
Willy Tarreau93893792009-07-23 13:19:11 +02003247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003249 }
3250 newsrv->state |= SRV_BIND_SRC;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003251 newsrv->source_addr = *str2sa_range(args[cur_arg + 1], &port_low, &port_high);
3252
3253 if (port_low != port_high) {
3254 int i;
3255 if (port_low <= 0 || port_low > 65535 ||
3256 port_high <= 0 || port_high > 65535 ||
3257 port_low > port_high) {
3258 Alert("parsing [%s:%d] : invalid source port range %d-%d.\n",
3259 file, linenum, port_low, port_high);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Willy Tarreauc6f4ce82009-06-10 11:09:37 +02003262 }
3263 newsrv->sport_range = port_range_alloc_range(port_high - port_low + 1);
3264 for (i = 0; i < newsrv->sport_range->size; i++)
3265 newsrv->sport_range->ports[i] = port_low + i;
3266 }
3267
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 cur_arg += 2;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003269 while (*(args[cur_arg])) {
3270 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003271#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3272#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003273 if (newsrv->source_addr.sin_addr.s_addr == INADDR_ANY) {
3274 Alert("parsing [%s:%d] : '%s' requires an explicit '%s' address.\n",
3275 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003278 }
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003279#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003280 if (!*args[cur_arg + 1]) {
3281 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3282 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003285 }
3286 if (!strcmp(args[cur_arg + 1], "client")) {
3287 newsrv->state |= SRV_TPROXY_CLI;
3288 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3289 newsrv->state |= SRV_TPROXY_CIP;
3290 } else {
3291 newsrv->state |= SRV_TPROXY_ADDR;
3292 newsrv->tproxy_addr = *str2sa(args[cur_arg + 1]);
3293 }
3294 global.last_checks |= LSTCHK_NETADM;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003295#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreauc76721d2009-02-04 20:20:58 +01003296 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003297#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003298 cur_arg += 2;
3299 continue;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003300#else /* no TPROXY support */
Willy Tarreauc76721d2009-02-04 20:20:58 +01003301 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003302 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003305#endif /* defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY) */
3306 } /* "usesrc" */
3307
3308 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3309#ifdef SO_BINDTODEVICE
3310 if (!*args[cur_arg + 1]) {
3311 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3312 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
Willy Tarreauc76721d2009-02-04 20:20:58 +01003315 }
3316 if (newsrv->iface_name)
3317 free(newsrv->iface_name);
3318
3319 newsrv->iface_name = strdup(args[cur_arg + 1]);
3320 newsrv->iface_len = strlen(newsrv->iface_name);
3321 global.last_checks |= LSTCHK_NETADM;
3322#else
3323 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3324 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreau77074d52006-11-12 23:57:19 +01003327#endif
Willy Tarreauc76721d2009-02-04 20:20:58 +01003328 cur_arg += 2;
3329 continue;
3330 }
3331 /* this keyword in not an option of "source" */
3332 break;
3333 } /* while */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003335 else if (!defsrv && !strcmp(args[cur_arg], "usesrc")) { /* address to use outside: needs "source" first */
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003336 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3337 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
3339 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003340 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 else {
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003342 if (!defsrv)
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003343 Alert("parsing [%s:%d] : server %s only supports options 'backup', 'cookie', 'redir', 'observer', 'on-error', 'error-limit', 'check', 'track', 'id', 'inter', 'fastinter', 'downinter', 'rise', 'fall', 'addr', 'port', 'source', 'minconn', 'maxconn', 'maxqueue', 'slowstart' and 'weight'.\n",
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003344 file, linenum, newsrv->id);
3345 else
Krzysztof Piotr Oledzkia9389b12010-01-05 16:44:17 +01003346 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 +01003347 file, linenum);
3348
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 }
3352 }
3353
3354 if (do_check) {
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003355 if (newsrv->trackit) {
3356 Alert("parsing [%s:%d]: unable to enable checks and tracking at the same time!\n",
3357 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003358 err_code |= ERR_ALERT | ERR_FATAL;
3359 goto out;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01003360 }
3361
Willy Tarreau0f03c6f2007-03-25 20:46:19 +02003362 if (!newsrv->check_port && newsrv->check_addr.sin_port)
3363 newsrv->check_port = newsrv->check_addr.sin_port;
3364
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 if (!newsrv->check_port && !(newsrv->state & SRV_MAPPORTS))
3366 newsrv->check_port = realport; /* by default */
3367 if (!newsrv->check_port) {
Willy Tarreauef00b502007-01-07 02:40:09 +01003368 /* not yet valid, because no port was set on
3369 * the server either. We'll check if we have
3370 * a known port on the first listener.
3371 */
3372 struct listener *l;
3373 l = curproxy->listen;
3374 if (l) {
3375 int port;
3376 port = (l->addr.ss_family == AF_INET6)
3377 ? ntohs(((struct sockaddr_in6 *)(&l->addr))->sin6_port)
3378 : ntohs(((struct sockaddr_in *)(&l->addr))->sin_port);
3379 newsrv->check_port = port;
3380 }
3381 }
3382 if (!newsrv->check_port) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 Alert("parsing [%s:%d] : server %s has neither service port nor check port. Check has been disabled.\n",
3384 file, linenum, newsrv->id);
Willy Tarreau93893792009-07-23 13:19:11 +02003385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387 }
Krzysztof Piotr Oledzki09605412009-09-23 22:09:24 +02003388
3389 newsrv->check_status = HCHK_STATUS_INI;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 newsrv->state |= SRV_CHECKED;
3391 }
3392
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003393 if (!defsrv) {
3394 if (newsrv->state & SRV_BACKUP)
3395 curproxy->srv_bck++;
3396 else
3397 curproxy->srv_act++;
Willy Tarreaub625a082007-11-26 01:15:43 +01003398
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01003399 newsrv->prev_state = newsrv->state;
3400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 }
3402 else if (!strcmp(args[0], "log")) { /* syslog server address */
Robert Tsai81ae1952007-12-05 10:47:29 +01003403 struct logsrv logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 int facility;
3405
3406 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
3407 curproxy->logfac1 = global.logfac1;
3408 curproxy->logsrv1 = global.logsrv1;
3409 curproxy->loglev1 = global.loglev1;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003410 curproxy->minlvl1 = global.minlvl1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 curproxy->logfac2 = global.logfac2;
3412 curproxy->logsrv2 = global.logsrv2;
3413 curproxy->loglev2 = global.loglev2;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003414 curproxy->minlvl2 = global.minlvl2;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 }
3416 else if (*(args[1]) && *(args[2])) {
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003417 int level, minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418
3419 facility = get_log_facility(args[2]);
3420 if (facility < 0) {
3421 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[2]);
3422 exit(1);
3423 }
3424
3425 level = 7; /* max syslog level = debug */
3426 if (*(args[3])) {
3427 level = get_log_level(args[3]);
3428 if (level < 0) {
3429 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[3]);
3430 exit(1);
3431 }
3432 }
3433
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003434 minlvl = 0; /* limit syslog level to this level (emerg) */
3435 if (*(args[4])) {
3436 minlvl = get_log_level(args[4]);
3437 if (level < 0) {
3438 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[4]);
3439 exit(1);
3440 }
3441 }
3442
Robert Tsai81ae1952007-12-05 10:47:29 +01003443 if (args[1][0] == '/') {
3444 logsrv.u.addr.sa_family = AF_UNIX;
3445 logsrv.u.un = *str2sun(args[1]);
3446 } else {
3447 logsrv.u.addr.sa_family = AF_INET;
3448 logsrv.u.in = *str2sa(args[1]);
3449 if (!logsrv.u.in.sin_port) {
3450 logsrv.u.in.sin_port =
3451 htons(SYSLOG_PORT);
3452 }
3453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003454
3455 if (curproxy->logfac1 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003456 curproxy->logsrv1 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 curproxy->logfac1 = facility;
3458 curproxy->loglev1 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003459 curproxy->minlvl1 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003460 }
3461 else if (curproxy->logfac2 == -1) {
Robert Tsai81ae1952007-12-05 10:47:29 +01003462 curproxy->logsrv2 = logsrv;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003463 curproxy->logfac2 = facility;
3464 curproxy->loglev2 = level;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02003465 curproxy->minlvl2 = minlvl;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003466 }
3467 else {
3468 Alert("parsing [%s:%d] : too many syslog servers\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471 }
3472 }
3473 else {
3474 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
3475 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003476 err_code |= ERR_ALERT | ERR_FATAL;
3477 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 }
3479 }
3480 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003481 int cur_arg;
3482
Willy Tarreau977b8e42006-12-29 14:19:17 +01003483 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003485
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003487 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
3488 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 }
Willy Tarreau368480c2009-03-01 08:27:21 +01003492
3493 /* we must first clear any optional default setting */
3494 curproxy->options &= ~PR_O_TPXY_MASK;
3495 free(curproxy->iface_name);
3496 curproxy->iface_name = NULL;
3497 curproxy->iface_len = 0;
3498
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 curproxy->source_addr = *str2sa(args[1]);
3500 curproxy->options |= PR_O_BIND_SRC;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003501
3502 cur_arg = 2;
3503 while (*(args[cur_arg])) {
3504 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003505#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_LINUX_TPROXY)
3506#if !defined(CONFIG_HAP_LINUX_TPROXY)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003507 if (curproxy->source_addr.sin_addr.s_addr == INADDR_ANY) {
3508 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
3509 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003512 }
3513#endif
3514 if (!*args[cur_arg + 1]) {
3515 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
3516 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003517 err_code |= ERR_ALERT | ERR_FATAL;
3518 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003519 }
3520
3521 if (!strcmp(args[cur_arg + 1], "client")) {
3522 curproxy->options |= PR_O_TPXY_CLI;
3523 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
3524 curproxy->options |= PR_O_TPXY_CIP;
3525 } else {
3526 curproxy->options |= PR_O_TPXY_ADDR;
3527 curproxy->tproxy_addr = *str2sa(args[cur_arg + 1]);
3528 }
3529 global.last_checks |= LSTCHK_NETADM;
3530#if !defined(CONFIG_HAP_LINUX_TPROXY)
3531 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003532#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003533#else /* no TPROXY support */
3534 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01003535 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003538#endif
3539 cur_arg += 2;
3540 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01003541 }
3542
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003543 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
3544#ifdef SO_BINDTODEVICE
3545 if (!*args[cur_arg + 1]) {
3546 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3547 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003548 err_code |= ERR_ALERT | ERR_FATAL;
3549 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003550 }
3551 if (curproxy->iface_name)
3552 free(curproxy->iface_name);
3553
3554 curproxy->iface_name = strdup(args[cur_arg + 1]);
3555 curproxy->iface_len = strlen(curproxy->iface_name);
3556 global.last_checks |= LSTCHK_NETADM;
3557#else
3558 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3559 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01003562#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01003563 cur_arg += 2;
3564 continue;
3565 }
3566 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3567 file, linenum, args[0], "inteface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003570 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003572 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3573 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3574 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02003575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01003577 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
3579 regex_t *preg;
3580 if (curproxy == &defproxy) {
3581 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003582 err_code |= ERR_ALERT | ERR_FATAL;
3583 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003585 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003587
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 if (*(args[1]) == 0 || *(args[2]) == 0) {
3589 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3590 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 }
3594
3595 preg = calloc(1, sizeof(regex_t));
3596 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3597 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003598 err_code |= ERR_ALERT | ERR_FATAL;
3599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 }
3601
3602 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3603 if (err) {
3604 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3605 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003608 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003609 }
3610 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
3611 regex_t *preg;
3612 if (curproxy == &defproxy) {
3613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003614 err_code |= ERR_ALERT | ERR_FATAL;
3615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003616 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003617 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003618 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003619
Willy Tarreaubaaee002006-06-26 02:48:02 +02003620 if (*(args[1]) == 0) {
3621 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003622 err_code |= ERR_ALERT | ERR_FATAL;
3623 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 }
3625
3626 preg = calloc(1, sizeof(regex_t));
3627 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3628 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 }
3632
3633 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003634 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 }
3636 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
3637 regex_t *preg;
3638 if (curproxy == &defproxy) {
3639 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003640 err_code |= ERR_ALERT | ERR_FATAL;
3641 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003643 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003644 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003645
Willy Tarreaubaaee002006-06-26 02:48:02 +02003646 if (*(args[1]) == 0) {
3647 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003648 err_code |= ERR_ALERT | ERR_FATAL;
3649 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003650 }
3651
3652 preg = calloc(1, sizeof(regex_t));
3653 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3654 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 }
3658
3659 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003660 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 }
3662 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
3663 regex_t *preg;
3664 if (curproxy == &defproxy) {
3665 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003669 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003670 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003671
Willy Tarreaubaaee002006-06-26 02:48:02 +02003672 if (*(args[1]) == 0) {
3673 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003676 }
3677
3678 preg = calloc(1, sizeof(regex_t));
3679 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3680 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003683 }
3684
3685 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003686 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003687 }
3688 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
3689 regex_t *preg;
3690 if (curproxy == &defproxy) {
3691 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003694 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003695 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003696 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003697
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 if (*(args[1]) == 0) {
3699 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003700 err_code |= ERR_ALERT | ERR_FATAL;
3701 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 }
3703
3704 preg = calloc(1, sizeof(regex_t));
3705 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3706 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 }
3710
3711 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003712 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003713 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003714 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
3715 regex_t *preg;
3716 if (curproxy == &defproxy) {
3717 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003718 err_code |= ERR_ALERT | ERR_FATAL;
3719 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003720 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003721 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003722 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003723
Willy Tarreaub8750a82006-09-03 09:56:00 +02003724 if (*(args[1]) == 0) {
3725 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003726 err_code |= ERR_ALERT | ERR_FATAL;
3727 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003728 }
3729
3730 preg = calloc(1, sizeof(regex_t));
3731 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3732 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003735 }
3736
3737 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003738 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003739 }
Willy Tarreaua496b602006-12-17 23:15:24 +01003740 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
3741 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003742 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003743 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003744 err_code |= ERR_ALERT | ERR_FATAL;
3745 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003746 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003747 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003749
Willy Tarreau977b8e42006-12-29 14:19:17 +01003750 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003751 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3752 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003755 }
3756
3757 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003758 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003759 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003762 }
3763
3764 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003765 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003766 }
3767 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
3768 regex_t *preg;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003769 if (curproxy == &defproxy) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003770 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_FATAL;
3772 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003773 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003774 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_WARN;
Willy Tarreaua496b602006-12-17 23:15:24 +01003776
Willy Tarreau977b8e42006-12-29 14:19:17 +01003777 if (*(args[1]) == 0 || *(args[2]) == 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003778 Alert("parsing [%s:%d] : '%s' expects <search> and <target> as arguments.\n",
3779 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003782 }
3783
3784 preg = calloc(1, sizeof(regex_t));
Willy Tarreau977b8e42006-12-29 14:19:17 +01003785 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
Willy Tarreaua496b602006-12-17 23:15:24 +01003786 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaua496b602006-12-17 23:15:24 +01003789 }
3790
3791 chain_regex(&curproxy->req_exp, preg, ACT_SETBE, strdup(args[2]));
Willy Tarreau61d18892009-03-31 10:49:21 +02003792 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaua496b602006-12-17 23:15:24 +01003793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003794 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
3795 regex_t *preg;
3796 if (curproxy == &defproxy) {
3797 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003800 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003801 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003803
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 if (*(args[1]) == 0 || *(args[2]) == 0) {
3805 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3806 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 }
3810
3811 preg = calloc(1, sizeof(regex_t));
3812 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3813 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003816 }
3817
3818 err = chain_regex(&curproxy->req_exp, preg, ACT_REPLACE, strdup(args[2]));
3819 if (err) {
3820 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
3821 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
Willy Tarreau61d18892009-03-31 10:49:21 +02003825 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003826 }
3827 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
3828 regex_t *preg;
3829 if (curproxy == &defproxy) {
3830 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003833 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003834 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003836
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 if (*(args[1]) == 0) {
3838 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
3842
3843 preg = calloc(1, sizeof(regex_t));
3844 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3845 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
3849
3850 chain_regex(&curproxy->req_exp, preg, ACT_REMOVE, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003851 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
3853 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
3854 regex_t *preg;
3855 if (curproxy == &defproxy) {
3856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_ALERT | ERR_FATAL;
3858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003860 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003862
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 if (*(args[1]) == 0) {
3864 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003865 err_code |= ERR_ALERT | ERR_FATAL;
3866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 }
3868
3869 preg = calloc(1, sizeof(regex_t));
3870 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3871 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003872 err_code |= ERR_ALERT | ERR_FATAL;
3873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003874 }
3875
3876 chain_regex(&curproxy->req_exp, preg, ACT_DENY, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003877 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003878 }
3879 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
3880 regex_t *preg;
3881 if (curproxy == &defproxy) {
3882 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003886 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003887 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003888
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 if (*(args[1]) == 0) {
3890 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003891 err_code |= ERR_ALERT | ERR_FATAL;
3892 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003893 }
3894
3895 preg = calloc(1, sizeof(regex_t));
3896 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3897 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003898 err_code |= ERR_ALERT | ERR_FATAL;
3899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003900 }
3901
3902 chain_regex(&curproxy->req_exp, preg, ACT_PASS, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003903 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 }
3905 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
3906 regex_t *preg;
3907 if (curproxy == &defproxy) {
3908 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003909 err_code |= ERR_ALERT | ERR_FATAL;
3910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003911 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003912 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003913 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003914
Willy Tarreaubaaee002006-06-26 02:48:02 +02003915 if (*(args[1]) == 0) {
3916 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003917 err_code |= ERR_ALERT | ERR_FATAL;
3918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 }
3920
3921 preg = calloc(1, sizeof(regex_t));
3922 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3923 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 }
3927
3928 chain_regex(&curproxy->req_exp, preg, ACT_ALLOW, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003929 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003930 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02003931 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
3932 regex_t *preg;
3933 if (curproxy == &defproxy) {
3934 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003937 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003938 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003940
Willy Tarreaub8750a82006-09-03 09:56:00 +02003941 if (*(args[1]) == 0) {
3942 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003943 err_code |= ERR_ALERT | ERR_FATAL;
3944 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003945 }
3946
3947 preg = calloc(1, sizeof(regex_t));
3948 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
3949 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003950 err_code |= ERR_ALERT | ERR_FATAL;
3951 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02003952 }
3953
3954 chain_regex(&curproxy->req_exp, preg, ACT_TARPIT, NULL);
Willy Tarreau61d18892009-03-31 10:49:21 +02003955 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaub8750a82006-09-03 09:56:00 +02003956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003957 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003958 struct wordlist *wl;
3959
Willy Tarreaubaaee002006-06-26 02:48:02 +02003960 if (curproxy == &defproxy) {
3961 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003962 err_code |= ERR_ALERT | ERR_FATAL;
3963 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003964 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003965 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003966 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003967
Willy Tarreaubaaee002006-06-26 02:48:02 +02003968 if (*(args[1]) == 0) {
3969 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003972 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01003973
3974 wl = calloc(1, sizeof(*wl));
3975 wl->s = strdup(args[1]);
3976 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02003977 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003978 }
3979 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
3980 regex_t *preg;
3981
3982 if (*(args[1]) == 0 || *(args[2]) == 0) {
3983 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
3984 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003985 err_code |= ERR_ALERT | ERR_FATAL;
3986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003987 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003988 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003989 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003990
Willy Tarreaubaaee002006-06-26 02:48:02 +02003991 preg = calloc(1, sizeof(regex_t));
3992 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
3993 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003996 }
3997
3998 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
3999 if (err) {
4000 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4001 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004002 err_code |= ERR_ALERT | ERR_FATAL;
4003 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004004 }
Willy Tarreau61d18892009-03-31 10:49:21 +02004005 warnif_misplaced_reqxxx(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004006 }
4007 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
4008 regex_t *preg;
4009 if (curproxy == &defproxy) {
4010 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004013 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004014 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004015 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004016
Willy Tarreaubaaee002006-06-26 02:48:02 +02004017 if (*(args[1]) == 0) {
4018 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004021 }
4022
4023 preg = calloc(1, sizeof(regex_t));
4024 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4025 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004026 err_code |= ERR_ALERT | ERR_FATAL;
4027 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004028 }
4029
4030 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4031 if (err) {
4032 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4033 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004034 err_code |= ERR_ALERT | ERR_FATAL;
4035 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004036 }
4037 }
4038 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
4039 regex_t *preg;
4040 if (curproxy == &defproxy) {
4041 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004042 err_code |= ERR_ALERT | ERR_FATAL;
4043 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004044 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004045 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004046 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004047
Willy Tarreaubaaee002006-06-26 02:48:02 +02004048 if (*(args[1]) == 0) {
4049 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004050 err_code |= ERR_ALERT | ERR_FATAL;
4051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004052 }
4053
4054 preg = calloc(1, sizeof(regex_t));
4055 if (regcomp(preg, args[1], REG_EXTENDED) != 0) {
4056 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004057 err_code |= ERR_ALERT | ERR_FATAL;
4058 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004059 }
4060
4061 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4062 if (err) {
4063 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4064 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004067 }
4068 }
4069 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
4070 regex_t *preg;
4071 if (curproxy == &defproxy) {
4072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004075 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004076 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004077 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004078
4079 if (*(args[1]) == 0 || *(args[2]) == 0) {
4080 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
4081 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004084 }
4085
4086 preg = calloc(1, sizeof(regex_t));
4087 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4088 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004091 }
4092
4093 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REPLACE, strdup(args[2]));
4094 if (err) {
4095 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4096 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004099 }
4100 }
4101 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
4102 regex_t *preg;
4103 if (curproxy == &defproxy) {
4104 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004108 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004110
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111 if (*(args[1]) == 0) {
4112 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004113 err_code |= ERR_ALERT | ERR_FATAL;
4114 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004115 }
4116
4117 preg = calloc(1, sizeof(regex_t));
4118 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4119 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 }
4123
4124 err = chain_regex(&curproxy->rsp_exp, preg, ACT_REMOVE, strdup(args[2]));
4125 if (err) {
4126 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4127 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 }
4131 }
4132 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
4133 regex_t *preg;
4134 if (curproxy == &defproxy) {
4135 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004136 err_code |= ERR_ALERT | ERR_FATAL;
4137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004139 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004140 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004141
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 if (*(args[1]) == 0) {
4143 Alert("parsing [%s:%d] : '%s' expects <search> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004144 err_code |= ERR_ALERT | ERR_FATAL;
4145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004146 }
4147
4148 preg = calloc(1, sizeof(regex_t));
4149 if (regcomp(preg, args[1], REG_EXTENDED | REG_ICASE) != 0) {
4150 Alert("parsing [%s:%d] : bad regular expression '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004153 }
4154
4155 err = chain_regex(&curproxy->rsp_exp, preg, ACT_DENY, strdup(args[2]));
4156 if (err) {
4157 Alert("parsing [%s:%d] : invalid character or unterminated sequence in replacement string near '%c'.\n",
4158 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004159 err_code |= ERR_ALERT | ERR_FATAL;
4160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 }
4162 }
4163 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004164 struct wordlist *wl;
4165
Willy Tarreaubaaee002006-06-26 02:48:02 +02004166 if (curproxy == &defproxy) {
4167 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004168 err_code |= ERR_ALERT | ERR_FATAL;
4169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004170 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004171 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004173
Willy Tarreaubaaee002006-06-26 02:48:02 +02004174 if (*(args[1]) == 0) {
4175 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004176 err_code |= ERR_ALERT | ERR_FATAL;
4177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 }
4179
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01004180 wl = calloc(1, sizeof(*wl));
4181 wl->s = strdup(args[1]);
4182 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 }
4184 else if (!strcmp(args[0], "errorloc") ||
4185 !strcmp(args[0], "errorloc302") ||
4186 !strcmp(args[0], "errorloc303")) { /* error location */
4187 int errnum, errlen;
4188 char *err;
4189
Willy Tarreau977b8e42006-12-29 14:19:17 +01004190 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004192
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004194 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_FATAL;
4196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 }
4198
4199 errnum = atol(args[1]);
4200 if (!strcmp(args[0], "errorloc303")) {
4201 err = malloc(strlen(HTTP_303) + strlen(args[2]) + 5);
4202 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_303, args[2]);
4203 } else {
4204 err = malloc(strlen(HTTP_302) + strlen(args[2]) + 5);
4205 errlen = sprintf(err, "%s%s\r\n\r\n", HTTP_302, args[2]);
4206 }
4207
Willy Tarreau0f772532006-12-23 20:51:41 +01004208 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4209 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004210 chunk_destroy(&curproxy->errmsg[rc]);
4211 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01004212 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004214 }
Willy Tarreau0f772532006-12-23 20:51:41 +01004215
4216 if (rc >= HTTP_ERR_SIZE) {
4217 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
4218 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004219 free(err);
4220 }
4221 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02004222 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
4223 int errnum, errlen, fd;
4224 char *err;
4225 struct stat stat;
4226
4227 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004229
4230 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02004231 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_ALERT | ERR_FATAL;
4233 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004234 }
4235
4236 fd = open(args[2], O_RDONLY);
4237 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
4238 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
4239 file, linenum, args[2], args[1]);
4240 if (fd >= 0)
4241 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02004242 err_code |= ERR_ALERT | ERR_FATAL;
4243 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004244 }
4245
Willy Tarreau27a674e2009-08-17 07:23:33 +02004246 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02004247 errlen = stat.st_size;
4248 } else {
4249 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02004250 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02004252 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004253 }
4254
4255 err = malloc(errlen); /* malloc() must succeed during parsing */
4256 errnum = read(fd, err, errlen);
4257 if (errnum != errlen) {
4258 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
4259 file, linenum, args[2], args[1]);
4260 close(fd);
4261 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02004262 err_code |= ERR_ALERT | ERR_FATAL;
4263 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004264 }
4265 close(fd);
4266
4267 errnum = atol(args[1]);
4268 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
4269 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02004270 chunk_destroy(&curproxy->errmsg[rc]);
4271 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02004272 break;
4273 }
4274 }
4275
4276 if (rc >= HTTP_ERR_SIZE) {
4277 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
4278 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02004279 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02004280 free(err);
4281 }
4282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004283 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004284 struct cfg_kw_list *kwl;
4285 int index;
4286
4287 list_for_each_entry(kwl, &cfg_keywords.list, list) {
4288 for (index = 0; kwl->kw[index].kw != NULL; index++) {
4289 if (kwl->kw[index].section != CFG_LISTEN)
4290 continue;
4291 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
4292 /* prepare error message just in case */
4293 snprintf(trash, sizeof(trash),
4294 "error near '%s' in %s section", args[0], cursection);
Willy Tarreau39f23b62008-07-09 20:22:56 +02004295 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, trash, sizeof(trash));
4296 if (rc < 0) {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004297 Alert("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004300 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02004301 else if (rc > 0) {
4302 Warning("parsing [%s:%d] : %s\n", file, linenum, trash);
Willy Tarreau93893792009-07-23 13:19:11 +02004303 err_code |= ERR_WARN;
4304 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02004305 }
Willy Tarreau93893792009-07-23 13:19:11 +02004306 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02004307 }
4308 }
4309 }
4310
Willy Tarreau6daf3432008-01-22 16:44:08 +01004311 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02004312 err_code |= ERR_ALERT | ERR_FATAL;
4313 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004314 }
Willy Tarreau93893792009-07-23 13:19:11 +02004315 out:
4316 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004317}
4318
4319
4320/*
4321 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02004322 * Returns the error code, 0 if OK, or any combination of :
4323 * - ERR_ABORT: must abort ASAP
4324 * - ERR_FATAL: we can continue parsing but not start the service
4325 * - ERR_WARN: a warning has been emitted
4326 * - ERR_ALERT: an alert has been emitted
4327 * Only the two first ones can stop processing, the two others are just
4328 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004329 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02004330int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004332 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02004333 FILE *f;
4334 int linenum = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 int confsect = CFG_NONE;
Willy Tarreau058e9072009-07-20 09:30:05 +02004336 int err_code = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004337
Willy Tarreaubaaee002006-06-26 02:48:02 +02004338 if ((f=fopen(file,"r")) == NULL)
4339 return -1;
4340
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004341 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004342 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004343 char *end;
4344 char *args[MAX_LINE_ARGS + 1];
4345 char *line = thisline;
4346
Willy Tarreaubaaee002006-06-26 02:48:02 +02004347 linenum++;
4348
4349 end = line + strlen(line);
4350
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004351 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
4352 /* Check if we reached the limit and the last char is not \n.
4353 * Watch out for the last line without the terminating '\n'!
4354 */
4355 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02004356 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02004357 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004358 }
4359
Willy Tarreaubaaee002006-06-26 02:48:02 +02004360 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004361 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004362 line++;
4363
4364 arg = 0;
4365 args[arg] = line;
4366
4367 while (*line && arg < MAX_LINE_ARGS) {
4368 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
4369 * C equivalent value. Other combinations left unchanged (eg: \1).
4370 */
4371 if (*line == '\\') {
4372 int skip = 0;
4373 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
4374 *line = line[1];
4375 skip = 1;
4376 }
4377 else if (line[1] == 'r') {
4378 *line = '\r';
4379 skip = 1;
4380 }
4381 else if (line[1] == 'n') {
4382 *line = '\n';
4383 skip = 1;
4384 }
4385 else if (line[1] == 't') {
4386 *line = '\t';
4387 skip = 1;
4388 }
4389 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004390 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004391 unsigned char hex1, hex2;
4392 hex1 = toupper(line[2]) - '0';
4393 hex2 = toupper(line[3]) - '0';
4394 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
4395 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
4396 *line = (hex1<<4) + hex2;
4397 skip = 3;
4398 }
4399 else {
4400 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004401 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004402 }
4403 }
4404 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01004405 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004406 end -= skip;
4407 }
4408 line++;
4409 }
4410 else if (*line == '#' || *line == '\n' || *line == '\r') {
4411 /* end of string, end of loop */
4412 *line = 0;
4413 break;
4414 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004415 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004416 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01004417 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02004418 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02004419 line++;
4420 args[++arg] = line;
4421 }
4422 else {
4423 line++;
4424 }
4425 }
4426
4427 /* empty line */
4428 if (!**args)
4429 continue;
4430
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004431 if (*line) {
4432 /* we had to stop due to too many args.
4433 * Let's terminate the string, print the offending part then cut the
4434 * last arg.
4435 */
4436 while (*line && *line != '#' && *line != '\n' && *line != '\r')
4437 line++;
4438 *line = '\0';
4439
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01004440 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01004441 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01004442 err_code |= ERR_ALERT | ERR_FATAL;
4443 args[arg] = line;
4444 }
4445
Willy Tarreau540abe42007-05-02 20:50:16 +02004446 /* zero out remaining args and ensure that at least one entry
4447 * is zeroed out.
4448 */
4449 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004450 args[arg] = line;
4451 }
4452
Willy Tarreau3842f002009-06-14 11:39:52 +02004453 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004454 if (!strcmp(args[0], "no")) {
Willy Tarreau3842f002009-06-14 11:39:52 +02004455 kwm = KWM_NO;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004456 for (arg=0; *args[arg+1]; arg++)
4457 args[arg] = args[arg+1]; // shift args after inversion
4458 }
Willy Tarreau3842f002009-06-14 11:39:52 +02004459 else if (!strcmp(args[0], "default")) {
4460 kwm = KWM_DEF;
4461 for (arg=0; *args[arg+1]; arg++)
4462 args[arg] = args[arg+1]; // shift args after inversion
4463 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004464
Willy Tarreau3842f002009-06-14 11:39:52 +02004465 if (kwm != KWM_STD && strcmp(args[0], "option") != 0) {
4466 Alert("parsing [%s:%d]: negation/default currently supported only for options.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02004467 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004468 }
4469
Willy Tarreau977b8e42006-12-29 14:19:17 +01004470 if (!strcmp(args[0], "listen") ||
4471 !strcmp(args[0], "frontend") ||
4472 !strcmp(args[0], "backend") ||
4473 !strcmp(args[0], "ruleset") ||
Willy Tarreau6daf3432008-01-22 16:44:08 +01004474 !strcmp(args[0], "defaults")) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 confsect = CFG_LISTEN;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004476 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004477 cursection = strdup(args[0]);
4478 }
4479 else if (!strcmp(args[0], "global")) { /* global config */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004480 confsect = CFG_GLOBAL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02004481 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004482 cursection = strdup(args[0]);
4483 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 /* else it's a section keyword */
4485
4486 switch (confsect) {
4487 case CFG_LISTEN:
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= cfg_parse_listen(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004489 break;
4490 case CFG_GLOBAL:
Willy Tarreau058e9072009-07-20 09:30:05 +02004491 err_code |= cfg_parse_global(file, linenum, args, kwm);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004492 break;
4493 default:
4494 Alert("parsing [%s:%d] : unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02004495 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004496 }
Willy Tarreau058e9072009-07-20 09:30:05 +02004497
4498 if (err_code & ERR_ABORT)
4499 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004501 free(cursection);
Willy Tarreau6daf3432008-01-22 16:44:08 +01004502 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004503 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02004504 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004505}
4506
Willy Tarreaubb925012009-07-23 13:36:36 +02004507/*
4508 * Returns the error code, 0 if OK, or any combination of :
4509 * - ERR_ABORT: must abort ASAP
4510 * - ERR_FATAL: we can continue parsing but not start the service
4511 * - ERR_WARN: a warning has been emitted
4512 * - ERR_ALERT: an alert has been emitted
4513 * Only the two first ones can stop processing, the two others are just
4514 * indicators.
4515 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004516int check_config_validity()
4517{
4518 int cfgerr = 0;
4519 struct proxy *curproxy = NULL;
4520 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02004521 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004522 unsigned int next_pxid = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523
4524 /*
4525 * Now, check for the integrity of all that we have collected.
4526 */
4527
4528 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02004529 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530
Willy Tarreau55bc0f82009-03-15 14:51:53 +01004531 /* first, we will invert the proxy list order */
4532 curproxy = NULL;
4533 while (proxy) {
4534 struct proxy *next;
4535
4536 next = proxy->next;
4537 proxy->next = curproxy;
4538 curproxy = proxy;
4539 if (!next)
4540 break;
4541 proxy = next;
4542 }
4543
Willy Tarreaubaaee002006-06-26 02:48:02 +02004544 if ((curproxy = proxy) == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004545 Alert("config : no <listen> line. Nothing to do !\n");
Willy Tarreaubb925012009-07-23 13:36:36 +02004546 err_code |= ERR_ALERT | ERR_FATAL;
4547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004548 }
4549
4550 while (curproxy != NULL) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004551 struct switching_rule *rule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004552 struct sticking_rule *mrule;
Willy Tarreaue6b98942007-10-29 01:09:36 +01004553 struct listener *listener;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004554 unsigned int next_id;
4555
4556 if (!curproxy->uuid) {
4557 /* proxy ID not set, use automatic numbering with first
4558 * spare entry starting with next_pxid.
4559 */
4560 next_pxid = get_next_id(&used_proxy_id, next_pxid);
4561 curproxy->conf.id.key = curproxy->uuid = next_pxid;
4562 eb32_insert(&used_proxy_id, &curproxy->conf.id);
4563 next_pxid++;
4564 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004565
Willy Tarreaubaaee002006-06-26 02:48:02 +02004566 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02004567 /* ensure we don't keep listeners uselessly bound */
4568 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 curproxy = curproxy->next;
4570 continue;
4571 }
4572
Willy Tarreauff01a212009-03-15 13:46:16 +01004573 switch (curproxy->mode) {
4574 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004575 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004576 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004577 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
4578 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004579 cfgerr++;
4580 }
4581
4582 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004583 Warning("config : servers will be ignored for %s '%s'.\n",
4584 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004585 break;
4586
4587 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004588 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01004589 break;
4590
4591 case PR_MODE_HTTP:
Willy Tarreaua9fb0832009-07-10 20:53:53 +02004592 curproxy->acl_requires |= ACL_USE_L7_ANY;
Willy Tarreauff01a212009-03-15 13:46:16 +01004593 if ((curproxy->cookie_name != NULL) && (curproxy->srv == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004594 Alert("config : HTTP proxy %s has a cookie but no server list !\n",
4595 curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01004596 cfgerr++;
4597 }
4598 break;
4599 }
4600
4601 if ((curproxy->cap & PR_CAP_FE) && (curproxy->listen == NULL)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004602 Alert("config : %s '%s' has no listen address. Please either specify a valid address on the <listen> line, or use the <bind> keyword.\n",
4603 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004604 cfgerr++;
4605 }
Willy Tarreauff01a212009-03-15 13:46:16 +01004606
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004607 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004608 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004609 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004610 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
4611 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004612 cfgerr++;
4613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004614#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004615 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004616 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
4617 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004618 cfgerr++;
4619 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004620#endif
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004621 else if (*(int *)&curproxy->dispatch_addr.sin_addr != 0) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004622 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
4623 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004624 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01004625 }
4626 }
4627 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_HTTP_PROXY)) &&
4628 (*(int *)&curproxy->dispatch_addr.sin_addr == 0)) {
4629 /* If no LB algo is set in a backend, and we're not in
4630 * transparent mode, dispatch mode nor proxy mode, we
4631 * want to use balance roundrobin by default.
4632 */
4633 curproxy->lbprm.algo &= ~BE_LB_ALGO;
4634 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 }
4636 }
Willy Tarreau193cf932007-09-17 10:17:23 +02004637
Willy Tarreau82936582007-11-30 15:20:09 +01004638 if ((curproxy->options & PR_O_DISABLE404) && !(curproxy->options & PR_O_HTTP_CHK)) {
4639 curproxy->options &= ~PR_O_DISABLE404;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004640 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
4641 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004642 err_code |= ERR_WARN;
Willy Tarreau82936582007-11-30 15:20:09 +01004643 }
4644
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004645 /* if a default backend was specified, let's find it */
4646 if (curproxy->defbe.name) {
4647 struct proxy *target;
4648
Alex Williams96532db2009-11-01 21:27:13 -05004649 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004650 if (!target) {
4651 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
4652 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004653 cfgerr++;
4654 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004655 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
4656 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02004657 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004658 } else {
4659 free(curproxy->defbe.name);
4660 curproxy->defbe.be = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004661 /* we force the backend to be present on at least all of
4662 * the frontend's processes.
4663 */
4664 target->bind_proc = curproxy->bind_proc ?
4665 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 }
4667 }
4668
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004669 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01004670 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
4671 /* map jump target for ACT_SETBE in req_rep chain */
4672 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01004673 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004674 struct proxy *target;
4675
Willy Tarreaua496b602006-12-17 23:15:24 +01004676 if (exp->action != ACT_SETBE)
4677 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004678
Alex Williams96532db2009-11-01 21:27:13 -05004679 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004680 if (!target) {
4681 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
4682 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01004683 cfgerr++;
4684 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004685 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
4686 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01004687 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01004688 } else {
4689 free((void *)exp->replace);
4690 exp->replace = (const char *)target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004691 /* we force the backend to be present on at least all of
4692 * the frontend's processes.
4693 */
4694 target->bind_proc = curproxy->bind_proc ?
4695 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreaua496b602006-12-17 23:15:24 +01004696 }
4697 }
4698 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004699
4700 /* find the target proxy for 'use_backend' rules */
4701 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02004702 struct proxy *target;
4703
Alex Williams96532db2009-11-01 21:27:13 -05004704 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004705
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004706 if (!target) {
4707 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
4708 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004709 cfgerr++;
4710 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01004711 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
4712 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004713 cfgerr++;
4714 } else {
4715 free((void *)rule->be.name);
4716 rule->be.backend = target;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01004717 /* we force the backend to be present on at least all of
4718 * the frontend's processes.
4719 */
4720 target->bind_proc = curproxy->bind_proc ?
4721 (target->bind_proc | curproxy->bind_proc) : 0;
Willy Tarreau55ea7572007-06-17 19:56:27 +02004722 }
4723 }
4724
Emeric Brunb982a3d2010-01-04 15:45:53 +01004725 /* find the target table for 'stick' rules */
4726 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
4727 struct proxy *target;
4728
Emeric Brun1d33b292010-01-04 15:47:17 +01004729 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
4730 if (mrule->flags & STK_IS_STORE)
4731 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4732
Emeric Brunb982a3d2010-01-04 15:45:53 +01004733 if (mrule->table.name)
4734 target = findproxy(mrule->table.name, PR_CAP_BE);
4735 else
4736 target = curproxy;
4737
4738 if (!target) {
4739 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
4740 curproxy->id, mrule->table.name);
4741 cfgerr++;
4742 }
4743 else if (target->table.size == 0) {
4744 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4745 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4746 cfgerr++;
4747 }
4748 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4749 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4750 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4751 cfgerr++;
4752 }
4753 else {
4754 free((void *)mrule->table.name);
4755 mrule->table.t = &(target->table);
4756 }
4757 }
4758
4759 /* find the target table for 'store response' rules */
4760 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
4761 struct proxy *target;
4762
Emeric Brun1d33b292010-01-04 15:47:17 +01004763 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
4764
Emeric Brunb982a3d2010-01-04 15:45:53 +01004765 if (mrule->table.name)
4766 target = findproxy(mrule->table.name, PR_CAP_BE);
4767 else
4768 target = curproxy;
4769
4770 if (!target) {
4771 Alert("Proxy '%s': unable to find store table '%s'.\n",
4772 curproxy->id, mrule->table.name);
4773 cfgerr++;
4774 }
4775 else if (target->table.size == 0) {
4776 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
4777 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4778 cfgerr++;
4779 }
4780 else if (pattern_notusable_key(mrule->expr, target->table.type)) {
4781 Alert("Proxy '%s': type of pattern not usable with type of stick-table '%s'.\n",
4782 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
4783 cfgerr++;
4784 }
4785 else {
4786 free((void *)mrule->table.name);
4787 mrule->table.t = &(target->table);
4788 }
4789 }
4790
Willy Tarreau2738a142006-07-08 17:28:09 +02004791 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004792 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02004793 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004794 (!curproxy->timeout.connect || !curproxy->timeout.server)))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004795 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02004796 " | While not properly invalid, you will certainly encounter various problems\n"
4797 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01004798 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004799 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004800 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02004801 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004802
Willy Tarreau1fa31262007-12-03 00:36:16 +01004803 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
4804 * We must still support older configurations, so let's find out whether those
4805 * parameters have been set or must be copied from contimeouts.
4806 */
4807 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004808 if (!curproxy->timeout.tarpit ||
4809 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004810 /* tarpit timeout not set. We search in the following order:
4811 * default.tarpit, curr.connect, default.connect.
4812 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004813 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004814 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004815 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004816 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004817 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004818 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004819 }
4820 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004821 (!curproxy->timeout.queue ||
4822 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01004823 /* queue timeout not set. We search in the following order:
4824 * default.queue, curr.connect, default.connect.
4825 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004826 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01004827 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004828 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004829 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02004830 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01004831 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01004832 }
4833 }
4834
Willy Tarreauf3c69202006-07-09 16:42:34 +02004835 if (curproxy->options & PR_O_SSL3_CHK) {
4836 curproxy->check_len = sizeof(sslv3_client_hello_pkt);
4837 curproxy->check_req = (char *)malloc(sizeof(sslv3_client_hello_pkt));
4838 memcpy(curproxy->check_req, sslv3_client_hello_pkt, sizeof(sslv3_client_hello_pkt));
4839 }
4840
Willy Tarreaucf7f3202007-05-13 22:46:04 +02004841 /* The small pools required for the capture lists */
4842 if (curproxy->nb_req_cap)
4843 curproxy->req_cap_pool = create_pool("ptrcap",
4844 curproxy->nb_req_cap * sizeof(char *),
4845 MEM_F_SHARED);
4846 if (curproxy->nb_rsp_cap)
4847 curproxy->rsp_cap_pool = create_pool("ptrcap",
4848 curproxy->nb_rsp_cap * sizeof(char *),
4849 MEM_F_SHARED);
4850
Willy Tarreau1d4154a2007-05-13 22:57:02 +02004851 curproxy->hdr_idx_pool = create_pool("hdr_idx",
4852 MAX_HTTP_HDR * sizeof(struct hdr_idx_elem),
4853 MEM_F_SHARED);
4854
Willy Tarreau86034312006-12-29 00:10:33 +01004855 /* for backwards compatibility with "listen" instances, if
4856 * fullconn is not set but maxconn is set, then maxconn
4857 * is used.
4858 */
4859 if (!curproxy->fullconn)
4860 curproxy->fullconn = curproxy->maxconn;
4861
Willy Tarreaubaaee002006-06-26 02:48:02 +02004862 /* first, we will invert the servers list order */
4863 newsrv = NULL;
4864 while (curproxy->srv) {
4865 struct server *next;
4866
4867 next = curproxy->srv->next;
4868 curproxy->srv->next = newsrv;
4869 newsrv = curproxy->srv;
4870 if (!next)
4871 break;
4872 curproxy->srv = next;
4873 }
4874
Willy Tarreau20697042007-11-15 23:26:18 +01004875 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01004876 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004878 /* We have to initialize the server lookup mechanism depending
4879 * on what LB algorithm was choosen.
4880 */
4881
4882 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
4883 switch (curproxy->lbprm.algo & BE_LB_KIND) {
4884 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02004885 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
4886 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4887 init_server_map(curproxy);
4888 } else {
4889 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
4890 fwrr_init_server_groups(curproxy);
4891 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004892 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004893
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004894 case BE_LB_KIND_LC:
4895 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
Willy Tarreau51406232008-03-10 22:04:20 +01004896 fwlc_init_server_tree(curproxy);
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004897 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004898
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004899 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004900 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
4901 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
4902 chash_init_server_tree(curproxy);
4903 } else {
4904 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
4905 init_server_map(curproxy);
4906 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02004907 break;
4908 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004909
4910 if (curproxy->options & PR_O_LOGASAP)
4911 curproxy->to_log &= ~LW_BYTES;
4912
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02004913 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
4914 (curproxy->cap & PR_CAP_FE) && curproxy->to_log && curproxy->logfac1 < 0) {
4915 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
4916 proxy_type_str(curproxy), curproxy->id);
4917 err_code |= ERR_WARN;
4918 }
4919
Willy Tarreaubaaee002006-06-26 02:48:02 +02004920 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01004921 * ensure that we're not cross-dressing a TCP server into HTTP.
4922 */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004923 next_id = 1;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004924 newsrv = curproxy->srv;
4925 while (newsrv != NULL) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02004926 if (!newsrv->puid) {
4927 /* server ID not set, use automatic numbering with first
4928 * spare entry starting with next_svid.
4929 */
4930 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
4931 newsrv->conf.id.key = newsrv->puid = next_id;
4932 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
4933 next_id++;
4934 }
4935
Willy Tarreau21d2af32008-02-14 20:25:24 +01004936 if ((curproxy->mode != PR_MODE_HTTP) && (newsrv->rdr_len || newsrv->cklen)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004937 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
4938 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004939 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01004940 }
4941 newsrv = newsrv->next;
4942 }
4943
4944 /*
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 * If this server supports a maxconn parameter, it needs a dedicated
4946 * tasks to fill the emptied slots when a connection leaves.
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004947 * Also, resolve deferred tracking dependency if needed.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004948 */
4949 newsrv = curproxy->srv;
4950 while (newsrv != NULL) {
Willy Tarreau86034312006-12-29 00:10:33 +01004951 if (newsrv->minconn > newsrv->maxconn) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 /* Only 'minconn' was specified, or it was higher than or equal
4953 * to 'maxconn'. Let's turn this into maxconn and clean it, as
4954 * this will avoid further useless expensive computations.
4955 */
4956 newsrv->maxconn = newsrv->minconn;
Willy Tarreau86034312006-12-29 00:10:33 +01004957 } else if (newsrv->maxconn && !newsrv->minconn) {
4958 /* minconn was not specified, so we set it to maxconn */
4959 newsrv->minconn = newsrv->maxconn;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004960 } else if (newsrv->minconn != newsrv->maxconn && !curproxy->fullconn) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004961 Alert("config : %s '%s' : fullconn is mandatory when minconn is set on a server.\n",
4962 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02004963 cfgerr++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
4965
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004966 if (newsrv->trackit) {
4967 struct proxy *px;
4968 struct server *srv;
4969 char *pname, *sname;
4970
4971 pname = newsrv->trackit;
4972 sname = strrchr(pname, '/');
4973
4974 if (sname)
4975 *sname++ = '\0';
4976 else {
4977 sname = pname;
4978 pname = NULL;
4979 }
4980
4981 if (pname) {
Alex Williams96532db2009-11-01 21:27:13 -05004982 px = findproxy(pname, PR_CAP_BE);
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004983 if (!px) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004984 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
4985 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004986 newsrv->id, pname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004987 cfgerr++;
4988 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004989 }
4990 } else
4991 px = curproxy;
4992
4993 srv = findserver(px, sname);
4994 if (!srv) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02004995 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
4996 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01004997 newsrv->id, sname);
Willy Tarreaubb925012009-07-23 13:36:36 +02004998 cfgerr++;
4999 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005000 }
5001
5002 if (!(srv->state & SRV_CHECKED)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005003 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Alex Williams96532db2009-11-01 21:27:13 -05005004 "tracking as it does not have checks enabled.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005005 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005006 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005007 cfgerr++;
5008 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005009 }
5010
5011 if (curproxy != px &&
5012 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005013 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005014 "tracing: disable-on-404 option inconsistency.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005015 proxy_type_str(curproxy), curproxy->id,
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005016 newsrv->id, px->id, srv->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02005017 cfgerr++;
5018 goto next_srv;
Krzysztof Piotr Oledzkic8b16fc2008-02-18 01:26:35 +01005019 }
5020
5021 newsrv->tracked = srv;
5022 newsrv->tracknext = srv->tracknext;
5023 srv->tracknext = newsrv;
5024
5025 free(newsrv->trackit);
5026 }
Willy Tarreaubb925012009-07-23 13:36:36 +02005027 next_srv:
Willy Tarreaubaaee002006-06-26 02:48:02 +02005028 newsrv = newsrv->next;
5029 }
5030
Willy Tarreauc1a21672009-08-16 22:37:44 +02005031 if (curproxy->cap & PR_CAP_FE) {
5032 if (curproxy->tcp_req.inspect_delay ||
5033 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
5034 curproxy->fe_req_ana |= AN_REQ_INSPECT;
5035
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005036 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005037 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005038 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005039 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005040
5041 /* both TCP and HTTP must check switching rules */
5042 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
5043 }
5044
5045 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005046 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02005047 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02005048 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02005049 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02005050
Emeric Brunb982a3d2010-01-04 15:45:53 +01005051 /* init table on backend capabilities proxy */
5052 stktable_init(&curproxy->table);
5053
Willy Tarreauc1a21672009-08-16 22:37:44 +02005054 /* If the backend does requires RDP cookie persistence, we have to
5055 * enable the corresponding analyser.
5056 */
5057 if (curproxy->options2 & PR_O2_RDPC_PRST)
5058 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
5059 }
5060
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005061 listener = NULL;
5062 while (curproxy->listen) {
5063 struct listener *next;
5064
5065 next = curproxy->listen->next;
5066 curproxy->listen->next = listener;
5067 listener = curproxy->listen;
5068
5069 if (!next)
5070 break;
5071
5072 curproxy->listen = next;
5073 }
5074
Willy Tarreaue6b98942007-10-29 01:09:36 +01005075 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005076 next_id = 1;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005077 listener = curproxy->listen;
5078 while (listener) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02005079 if (!listener->luid) {
5080 /* listener ID not set, use automatic numbering with first
5081 * spare entry starting with next_luid.
5082 */
5083 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
5084 listener->conf.id.key = listener->luid = next_id;
5085 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
5086 next_id++;
5087 }
5088
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02005089 /* enable separate counters */
5090 if (curproxy->options2 & PR_O2_SOCKSTAT) {
5091 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
5092 if (!listener->name) {
5093 sprintf(trash, "sock-%d", listener->luid);
5094 listener->name = strdup(trash);
5095 }
5096 }
5097
Willy Tarreaue6b98942007-10-29 01:09:36 +01005098 if (curproxy->options & PR_O_TCP_NOLING)
5099 listener->options |= LI_O_NOLINGER;
5100 listener->maxconn = curproxy->maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005101 listener->backlog = curproxy->backlog;
Willy Tarreaud7c30f92007-12-03 01:38:36 +01005102 listener->timeout = &curproxy->timeout.client;
Willy Tarreaue6b98942007-10-29 01:09:36 +01005103 listener->accept = event_accept;
5104 listener->private = curproxy;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005105 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02005106 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01005107
Willy Tarreau9ea05a72009-06-14 12:07:01 +02005108 /* smart accept mode is automatic in HTTP mode */
5109 if ((curproxy->options2 & PR_O2_SMARTACC) ||
5110 (curproxy->mode == PR_MODE_HTTP &&
5111 !(curproxy->no_options2 & PR_O2_SMARTACC)))
5112 listener->options |= LI_O_NOQUICKACK;
5113
Willy Tarreau1d0dfb12009-07-07 15:10:31 +02005114 /* We want the use_backend and default_backend rules to apply */
Willy Tarreaue6b98942007-10-29 01:09:36 +01005115 listener = listener->next;
5116 }
5117
Willy Tarreaubaaee002006-06-26 02:48:02 +02005118 curproxy = curproxy->next;
5119 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005120
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005121 /*
5122 * Recount currently required checks.
5123 */
5124
5125 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
5126 int optnum;
5127
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005128 for (optnum = 0; cfg_opts[optnum].name; optnum++)
5129 if (curproxy->options & cfg_opts[optnum].val)
5130 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005131
Willy Tarreau66aa61f2009-01-18 21:44:07 +01005132 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
5133 if (curproxy->options2 & cfg_opts2[optnum].val)
5134 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005135 }
5136
Willy Tarreaubb925012009-07-23 13:36:36 +02005137 if (cfgerr > 0)
5138 err_code |= ERR_ALERT | ERR_FATAL;
5139 out:
5140 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141}
5142
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005143/*
5144 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
5145 * parsing sessions.
5146 */
5147void cfg_register_keywords(struct cfg_kw_list *kwl)
5148{
5149 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
5150}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005152/*
5153 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
5154 */
5155void cfg_unregister_keywords(struct cfg_kw_list *kwl)
5156{
5157 LIST_DEL(&kwl->list);
5158 LIST_INIT(&kwl->list);
5159}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160
5161/*
5162 * Local variables:
5163 * c-indent-level: 8
5164 * c-basic-offset: 8
5165 * End:
5166 */