blob: 089c177a9fb7af9a521c8a40558a649b11711c27 [file] [log] [blame]
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <netdb.h>
5#include <ctype.h>
6#include <pwd.h>
7#include <grp.h>
8#include <errno.h>
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include <unistd.h>
13
Willy Tarreaudcc048a2020-06-04 19:11:43 +020014#include <haproxy/acl.h>
Willy Tarreau278161c2020-06-04 11:18:28 +020015#include <haproxy/capture-t.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020016#include <haproxy/cfgparse.h>
Willy Tarreau4aa573d2020-06-04 18:21:56 +020017#include <haproxy/check.h>
Willy Tarreau0a3bd392020-06-04 08:52:38 +020018#include <haproxy/compression-t.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020019#include <haproxy/connection.h>
Willy Tarreaubcc67332020-06-05 15:31:31 +020020#include <haproxy/extcheck.h>
Willy Tarreau87735332020-06-04 09:08:41 +020021#include <haproxy/http_htx.h>
Willy Tarreauc761f842020-06-04 11:40:28 +020022#include <haproxy/http_rules.h>
Willy Tarreau213e9902020-06-04 14:58:24 +020023#include <haproxy/listener.h>
Willy Tarreau36979d92020-06-05 17:27:29 +020024#include <haproxy/log.h>
Willy Tarreau872f2ea2020-06-04 18:46:44 +020025#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020026#include <haproxy/protocol.h>
Willy Tarreaua264d962020-06-04 22:29:18 +020027#include <haproxy/proxy.h>
Willy Tarreaue6ce10b2020-06-04 15:33:47 +020028#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +020029#include <haproxy/server.h>
Willy Tarreau2eec9b52020-06-04 19:58:55 +020030#include <haproxy/stats-t.h>
Willy Tarreau872f2ea2020-06-04 18:46:44 +020031#include <haproxy/stick_table.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020032#include <haproxy/tcpcheck.h>
33#include <haproxy/uri_auth.h>
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010034
35/* Report a warning if a rule is placed after a 'tcp-request session' rule.
36 * Return 1 if the warning has been emitted, otherwise 0.
37 */
38int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
39{
40 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
41 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
42 file, line, arg);
43 return 1;
44 }
45 return 0;
46}
47
48/* Report a warning if a rule is placed after a 'tcp-request content' rule.
49 * Return 1 if the warning has been emitted, otherwise 0.
50 */
51int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
52{
53 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
54 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
55 file, line, arg);
56 return 1;
57 }
58 return 0;
59}
60
61/* Report a warning if a rule is placed after a 'monitor fail' rule.
62 * Return 1 if the warning has been emitted, otherwise 0.
63 */
64int warnif_rule_after_monitor(struct proxy *proxy, const char *file, int line, const char *arg)
65{
66 if (!LIST_ISEMPTY(&proxy->mon_fail_cond)) {
67 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'monitor fail' rule will still be processed before.\n",
68 file, line, arg);
69 return 1;
70 }
71 return 0;
72}
73
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010074/* Report a warning if a rule is placed after an 'http_request' rule.
75 * Return 1 if the warning has been emitted, otherwise 0.
76 */
77int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
78{
79 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
80 ha_warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
81 file, line, arg);
82 return 1;
83 }
84 return 0;
85}
86
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +010087/* Report a warning if a rule is placed after a redirect rule.
88 * Return 1 if the warning has been emitted, otherwise 0.
89 */
90int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
91{
92 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
93 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
94 file, line, arg);
95 return 1;
96 }
97 return 0;
98}
99
100/* Report a warning if a rule is placed after a 'use_backend' rule.
101 * Return 1 if the warning has been emitted, otherwise 0.
102 */
103int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
104{
105 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
106 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
107 file, line, arg);
108 return 1;
109 }
110 return 0;
111}
112
113/* Report a warning if a rule is placed after a 'use-server' rule.
114 * Return 1 if the warning has been emitted, otherwise 0.
115 */
116int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
117{
118 if (!LIST_ISEMPTY(&proxy->server_rules)) {
119 ha_warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
120 file, line, arg);
121 return 1;
122 }
123 return 0;
124}
125
126/* report a warning if a redirect rule is dangerously placed */
127int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
128{
129 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
130 warnif_rule_after_use_server(proxy, file, line, arg);
131}
132
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100133/* report a warning if an http-request rule is dangerously placed */
134int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
135{
Christopher Faulet1b6adb42019-07-17 15:33:14 +0200136 return warnif_rule_after_redirect(proxy, file, line, arg) ||
137 warnif_misplaced_redirect(proxy, file, line, arg);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100138}
139
140/* report a warning if a block rule is dangerously placed */
Christopher Faulet8c3b63a2019-07-17 15:19:51 +0200141int warnif_misplaced_monitor(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100142{
143 return warnif_rule_after_http_req(proxy, file, line, arg) ||
144 warnif_misplaced_http_req(proxy, file, line, arg);
145}
146
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100147/* report a warning if a "tcp request content" rule is dangerously placed */
148int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
149{
150 return warnif_rule_after_monitor(proxy, file, line, arg) ||
151 warnif_misplaced_monitor(proxy, file, line, arg);
152}
153
154/* report a warning if a "tcp request session" rule is dangerously placed */
155int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
156{
157 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
158 warnif_misplaced_tcp_cont(proxy, file, line, arg);
159}
160
161/* report a warning if a "tcp request connection" rule is dangerously placed */
162int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
163{
164 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
165 warnif_misplaced_tcp_sess(proxy, file, line, arg);
166}
167
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100168int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
169{
170 static struct proxy *curproxy = NULL;
171 const char *err;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100172 int rc;
173 unsigned val;
174 int err_code = 0;
175 struct acl_cond *cond = NULL;
176 struct logsrv *tmplogsrv;
177 char *errmsg = NULL;
178 struct bind_conf *bind_conf;
179
180 if (!strcmp(args[0], "listen"))
181 rc = PR_CAP_LISTEN;
182 else if (!strcmp(args[0], "frontend"))
183 rc = PR_CAP_FE;
184 else if (!strcmp(args[0], "backend"))
185 rc = PR_CAP_BE;
186 else
187 rc = PR_CAP_NONE;
188
189 if (rc != PR_CAP_NONE) { /* new proxy */
190 if (!*args[1]) {
191 ha_alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
192 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
193 file, linenum, args[0]);
194 err_code |= ERR_ALERT | ERR_ABORT;
195 goto out;
196 }
197
198 err = invalid_char(args[1]);
199 if (err) {
200 ha_alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
201 file, linenum, *err, args[0], args[1]);
202 err_code |= ERR_ALERT | ERR_FATAL;
203 }
204
205 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
206 if (curproxy) {
207 ha_alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
208 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
209 curproxy->id, curproxy->conf.file, curproxy->conf.line);
210 err_code |= ERR_ALERT | ERR_FATAL;
211 }
212
213 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
214 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
215 err_code |= ERR_ALERT | ERR_ABORT;
216 goto out;
217 }
218
219 init_new_proxy(curproxy);
220 curproxy->next = proxies_list;
221 proxies_list = curproxy;
222 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
223 curproxy->conf.args.line = curproxy->conf.line = linenum;
224 curproxy->last_change = now.tv_sec;
225 curproxy->id = strdup(args[1]);
226 curproxy->cap = rc;
227 proxy_store_name(curproxy);
228
229 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
230 if (curproxy->cap & PR_CAP_FE)
231 ha_alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
232 goto out;
233 }
234
235 /* set default values */
236 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
237 curproxy->defsrv.id = "default-server";
238
239 curproxy->state = defproxy.state;
240 curproxy->options = defproxy.options;
241 curproxy->options2 = defproxy.options2;
242 curproxy->no_options = defproxy.no_options;
243 curproxy->no_options2 = defproxy.no_options2;
244 curproxy->bind_proc = defproxy.bind_proc;
245 curproxy->except_net = defproxy.except_net;
246 curproxy->except_mask = defproxy.except_mask;
247 curproxy->except_to = defproxy.except_to;
248 curproxy->except_mask_to = defproxy.except_mask_to;
Olivier Houcharda254a372019-04-05 15:30:12 +0200249 curproxy->retry_type = defproxy.retry_type;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100250
251 if (defproxy.fwdfor_hdr_len) {
252 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
253 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
254 }
255
256 if (defproxy.orgto_hdr_len) {
257 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
258 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
259 }
260
261 if (defproxy.server_id_hdr_len) {
262 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
263 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
264 }
265
266 /* initialize error relocations */
Christopher Faulet76edc0f2020-01-13 15:52:01 +0100267 if (!proxy_dup_default_conf_errors(curproxy, &defproxy, &errmsg)) {
268 ha_alert("parsing [%s:%d] : proxy '%s' : %s\n", file, linenum, curproxy->id, errmsg);
269 err_code |= ERR_ALERT | ERR_FATAL;
270 goto out;
271 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100272
273 if (curproxy->cap & PR_CAP_FE) {
274 curproxy->maxconn = defproxy.maxconn;
275 curproxy->backlog = defproxy.backlog;
276 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
277
278 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
Olivier Houcharda4d4fdf2018-12-14 19:27:06 +0100279 curproxy->max_out_conns = defproxy.max_out_conns;
MIZUTA Takeshib24bc0d2020-07-09 11:13:20 +0900280
281 curproxy->clitcpka_cnt = defproxy.clitcpka_cnt;
282 curproxy->clitcpka_idle = defproxy.clitcpka_idle;
283 curproxy->clitcpka_intvl = defproxy.clitcpka_intvl;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100284 }
285
286 if (curproxy->cap & PR_CAP_BE) {
287 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau76e84f52019-01-14 16:50:58 +0100288 curproxy->lbprm.hash_balance_factor = defproxy.lbprm.hash_balance_factor;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100289 curproxy->fullconn = defproxy.fullconn;
290 curproxy->conn_retries = defproxy.conn_retries;
291 curproxy->redispatch_after = defproxy.redispatch_after;
292 curproxy->max_ka_queue = defproxy.max_ka_queue;
293
Christopher Faulete5870d82020-04-15 11:32:03 +0200294 curproxy->tcpcheck_rules.flags = (defproxy.tcpcheck_rules.flags & ~TCPCHK_RULES_UNUSED_RS);
Christopher Faulet5d503fc2020-03-30 20:34:34 +0200295 curproxy->tcpcheck_rules.list = defproxy.tcpcheck_rules.list;
Christopher Faulet7a1e2e12020-04-02 18:05:11 +0200296 if (!LIST_ISEMPTY(&defproxy.tcpcheck_rules.preset_vars)) {
297 if (!dup_tcpcheck_vars(&curproxy->tcpcheck_rules.preset_vars,
298 &defproxy.tcpcheck_rules.preset_vars)) {
299 ha_alert("parsing [%s:%d] : failed to duplicate tcpcheck preset-vars\n",
300 file, linenum);
301 err_code |= ERR_ALERT | ERR_FATAL;
302 goto out;
303 }
304 }
Gaetan Rivet04578db2020-02-07 15:37:17 +0100305
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100306 curproxy->ck_opts = defproxy.ck_opts;
307 if (defproxy.cookie_name)
308 curproxy->cookie_name = strdup(defproxy.cookie_name);
309 curproxy->cookie_len = defproxy.cookie_len;
310
311 if (defproxy.dyncookie_key)
312 curproxy->dyncookie_key = strdup(defproxy.dyncookie_key);
313 if (defproxy.cookie_domain)
314 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
315
316 if (defproxy.cookie_maxidle)
317 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
318
319 if (defproxy.cookie_maxlife)
320 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
321
322 if (defproxy.rdp_cookie_name)
323 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
324 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
325
Christopher Faulet2f533902020-01-21 11:06:48 +0100326 if (defproxy.cookie_attrs)
327 curproxy->cookie_attrs = strdup(defproxy.cookie_attrs);
Willy Tarreau20e68372019-01-14 16:04:01 +0100328
Willy Tarreau4c03d1c2019-01-14 15:23:54 +0100329 if (defproxy.lbprm.arg_str)
330 curproxy->lbprm.arg_str = strdup(defproxy.lbprm.arg_str);
331 curproxy->lbprm.arg_len = defproxy.lbprm.arg_len;
Willy Tarreau20e68372019-01-14 16:04:01 +0100332 curproxy->lbprm.arg_opt1 = defproxy.lbprm.arg_opt1;
333 curproxy->lbprm.arg_opt2 = defproxy.lbprm.arg_opt2;
334 curproxy->lbprm.arg_opt3 = defproxy.lbprm.arg_opt3;
335
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100336 if (defproxy.conn_src.iface_name)
337 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
338 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
339 curproxy->conn_src.opts = defproxy.conn_src.opts;
340#if defined(CONFIG_HAP_TRANSPARENT)
341 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
342#endif
343 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
MIZUTA Takeshib24bc0d2020-07-09 11:13:20 +0900344
345 curproxy->srvtcpka_cnt = defproxy.srvtcpka_cnt;
346 curproxy->srvtcpka_idle = defproxy.srvtcpka_idle;
347 curproxy->srvtcpka_intvl = defproxy.srvtcpka_intvl;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100348 }
349
350 if (curproxy->cap & PR_CAP_FE) {
351 if (defproxy.capture_name)
352 curproxy->capture_name = strdup(defproxy.capture_name);
353 curproxy->capture_namelen = defproxy.capture_namelen;
354 curproxy->capture_len = defproxy.capture_len;
355 }
356
357 if (curproxy->cap & PR_CAP_FE) {
358 curproxy->timeout.client = defproxy.timeout.client;
359 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
360 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
361 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
362 curproxy->timeout.httpka = defproxy.timeout.httpka;
363 curproxy->mon_net = defproxy.mon_net;
364 curproxy->mon_mask = defproxy.mon_mask;
365 if (defproxy.monitor_uri)
366 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
367 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
368 if (defproxy.defbe.name)
369 curproxy->defbe.name = strdup(defproxy.defbe.name);
370
371 /* get either a pointer to the logformat string or a copy of it */
372 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
373 if (curproxy->conf.logformat_string &&
374 curproxy->conf.logformat_string != default_http_log_format &&
375 curproxy->conf.logformat_string != default_tcp_log_format &&
376 curproxy->conf.logformat_string != clf_http_log_format)
377 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
378
379 if (defproxy.conf.lfs_file) {
380 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
381 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
382 }
383
384 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
385 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
386 if (curproxy->conf.logformat_sd_string &&
387 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
388 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
389
390 if (defproxy.conf.lfsd_file) {
391 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
392 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
393 }
394 }
395
396 if (curproxy->cap & PR_CAP_BE) {
397 curproxy->timeout.connect = defproxy.timeout.connect;
398 curproxy->timeout.server = defproxy.timeout.server;
399 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
400 curproxy->timeout.check = defproxy.timeout.check;
401 curproxy->timeout.queue = defproxy.timeout.queue;
402 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
403 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
404 curproxy->timeout.httpka = defproxy.timeout.httpka;
405 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
406 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
407 }
408
409 curproxy->mode = defproxy.mode;
410 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
411
412 /* copy default logsrvs to curproxy */
413 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
414 struct logsrv *node = malloc(sizeof(*node));
415 memcpy(node, tmplogsrv, sizeof(struct logsrv));
416 node->ref = tmplogsrv->ref;
417 LIST_INIT(&node->list);
418 LIST_ADDQ(&curproxy->logsrvs, &node->list);
419 }
420
421 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
422 if (curproxy->conf.uniqueid_format_string)
423 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
424
425 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
426
427 if (defproxy.conf.uif_file) {
428 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
429 curproxy->conf.uif_line = defproxy.conf.uif_line;
430 }
431
432 /* copy default header unique id */
Tim Duesterhus0643b0e2020-03-05 17:56:35 +0100433 if (isttest(defproxy.header_unique_id)) {
434 const struct ist copy = istdup(defproxy.header_unique_id);
435 if (!isttest(copy)) {
436 ha_alert("parsing [%s:%d] : failed to allocate memory for unique-id-header\n", file, linenum);
437 err_code |= ERR_ALERT | ERR_FATAL;
438 goto out;
439 }
440 curproxy->header_unique_id = copy;
441 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100442
443 /* default compression options */
444 if (defproxy.comp != NULL) {
445 curproxy->comp = calloc(1, sizeof(struct comp));
446 curproxy->comp->algos = defproxy.comp->algos;
447 curproxy->comp->types = defproxy.comp->types;
448 }
449
450 curproxy->grace = defproxy.grace;
451 curproxy->conf.used_listener_id = EB_ROOT;
452 curproxy->conf.used_server_id = EB_ROOT;
453
454 if (defproxy.check_path)
455 curproxy->check_path = strdup(defproxy.check_path);
456 if (defproxy.check_command)
457 curproxy->check_command = strdup(defproxy.check_command);
458
459 if (defproxy.email_alert.mailers.name)
460 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
461 if (defproxy.email_alert.from)
462 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
463 if (defproxy.email_alert.to)
464 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
465 if (defproxy.email_alert.myhostname)
466 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
467 curproxy->email_alert.level = defproxy.email_alert.level;
468 curproxy->email_alert.set = defproxy.email_alert.set;
469
470 goto out;
471 }
472 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
473 /* some variables may have already been initialized earlier */
474 /* FIXME-20070101: we should do this too at the end of the
475 * config parsing to free all default values.
476 */
477 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
478 err_code |= ERR_ABORT;
479 goto out;
480 }
481
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100482 free(defproxy.check_command);
483 free(defproxy.check_path);
484 free(defproxy.cookie_name);
485 free(defproxy.rdp_cookie_name);
486 free(defproxy.dyncookie_key);
487 free(defproxy.cookie_domain);
Christopher Faulet2f533902020-01-21 11:06:48 +0100488 free(defproxy.cookie_attrs);
Willy Tarreau4c03d1c2019-01-14 15:23:54 +0100489 free(defproxy.lbprm.arg_str);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100490 free(defproxy.capture_name);
491 free(defproxy.monitor_uri);
492 free(defproxy.defbe.name);
493 free(defproxy.conn_src.iface_name);
494 free(defproxy.fwdfor_hdr_name);
495 defproxy.fwdfor_hdr_len = 0;
496 free(defproxy.orgto_hdr_name);
497 defproxy.orgto_hdr_len = 0;
498 free(defproxy.server_id_hdr_name);
499 defproxy.server_id_hdr_len = 0;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100500
501 if (defproxy.conf.logformat_string != default_http_log_format &&
502 defproxy.conf.logformat_string != default_tcp_log_format &&
503 defproxy.conf.logformat_string != clf_http_log_format)
504 free(defproxy.conf.logformat_string);
505
506 free(defproxy.conf.uniqueid_format_string);
507 free(defproxy.conf.lfs_file);
508 free(defproxy.conf.uif_file);
509 chunk_destroy(&defproxy.log_tag);
510 free_email_alert(&defproxy);
511
512 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
513 free(defproxy.conf.logformat_sd_string);
514 free(defproxy.conf.lfsd_file);
515
Christopher Faulet76edc0f2020-01-13 15:52:01 +0100516 proxy_release_conf_errors(&defproxy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100517
Christopher Faulet5d503fc2020-03-30 20:34:34 +0200518 deinit_proxy_tcpcheck(&defproxy);
519
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100520 /* we cannot free uri_auth because it might already be used */
521 init_default_instance();
522 curproxy = &defproxy;
523 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
524 curproxy->conf.args.line = curproxy->conf.line = linenum;
525 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
526 goto out;
527 }
528 else if (curproxy == NULL) {
529 ha_alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
530 err_code |= ERR_ALERT | ERR_FATAL;
531 goto out;
532 }
533
534 /* update the current file and line being parsed */
535 curproxy->conf.args.file = curproxy->conf.file;
536 curproxy->conf.args.line = linenum;
537
538 /* Now let's parse the proxy-specific keywords */
539 if (!strcmp(args[0], "server") ||
540 !strcmp(args[0], "default-server") ||
541 !strcmp(args[0], "server-template")) {
Emeric Brund3db3842020-07-21 16:54:36 +0200542 err_code |= parse_server(file, linenum, args, curproxy, &defproxy, 1, 0, 0);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100543 if (err_code & ERR_FATAL)
544 goto out;
545 }
546 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
547 struct listener *l;
548 int cur_arg;
549
550 if (curproxy == &defproxy) {
551 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
552 err_code |= ERR_ALERT | ERR_FATAL;
553 goto out;
554 }
555 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
556 err_code |= ERR_WARN;
557
558 if (!*(args[1])) {
559 ha_alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
560 file, linenum, args[0]);
561 err_code |= ERR_ALERT | ERR_FATAL;
562 goto out;
563 }
564
565 bind_conf = bind_conf_alloc(curproxy, file, linenum, args[1], xprt_get(XPRT_RAW));
566
567 /* use default settings for unix sockets */
568 bind_conf->ux.uid = global.unix_bind.ux.uid;
569 bind_conf->ux.gid = global.unix_bind.ux.gid;
570 bind_conf->ux.mode = global.unix_bind.ux.mode;
571
572 /* NOTE: the following line might create several listeners if there
573 * are comma-separated IPs or port ranges. So all further processing
574 * will have to be applied to all listeners created after last_listen.
575 */
576 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
577 if (errmsg && *errmsg) {
578 indent_msg(&errmsg, 2);
579 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
580 }
581 else
582 ha_alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
583 file, linenum, args[0], args[1]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586 }
587
588 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
589 /* Set default global rights and owner for unix bind */
590 global.maxsock++;
591 }
592
593 cur_arg = 2;
594 while (*(args[cur_arg])) {
595 static int bind_dumped;
596 struct bind_kw *kw;
597 char *err;
598
599 kw = bind_find_kw(args[cur_arg]);
600 if (kw) {
601 char *err = NULL;
602 int code;
603
604 if (!kw->parse) {
605 ha_alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
606 file, linenum, args[0], args[1], args[cur_arg]);
607 cur_arg += 1 + kw->skip ;
608 err_code |= ERR_ALERT | ERR_FATAL;
609 goto out;
610 }
611
612 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
613 err_code |= code;
614
615 if (code) {
616 if (err && *err) {
617 indent_msg(&err, 2);
Emeric Brun0655c9b2019-10-17 16:45:56 +0200618 if (((code & (ERR_WARN|ERR_ALERT)) == ERR_WARN))
619 ha_warning("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
620 else
621 ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100622 }
623 else
624 ha_alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
625 file, linenum, args[0], args[1], args[cur_arg]);
626 if (code & ERR_FATAL) {
627 free(err);
628 cur_arg += 1 + kw->skip;
629 goto out;
630 }
631 }
632 free(err);
633 cur_arg += 1 + kw->skip;
634 continue;
635 }
636
637 err = NULL;
638 if (!bind_dumped) {
639 bind_dump_kws(&err);
640 indent_msg(&err, 4);
641 bind_dumped = 1;
642 }
643
644 ha_alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
645 file, linenum, args[0], args[1], args[cur_arg],
646 err ? " Registered keywords :" : "", err ? err : "");
647 free(err);
648
649 err_code |= ERR_ALERT | ERR_FATAL;
650 goto out;
651 }
652 goto out;
653 }
654 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
655 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
656 ha_alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
657 file, linenum, args[0]);
658 err_code |= ERR_ALERT | ERR_FATAL;
659 goto out;
660 }
661 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
662 err_code |= ERR_WARN;
663
664 /* flush useless bits */
665 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
666 goto out;
667 }
668 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
669 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
670 err_code |= ERR_WARN;
671
672 if (alertif_too_many_args(1, file, linenum, args, &err_code))
673 goto out;
674
675 if (!*args[1]) {
676 ha_alert("parsing [%s:%d] : '%s' expects an URI.\n",
677 file, linenum, args[0]);
678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
680 }
681
682 free(curproxy->monitor_uri);
683 curproxy->monitor_uri_len = strlen(args[1]);
684 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
685 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
686 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
687
688 goto out;
689 }
690 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
691 if (alertif_too_many_args(1, file, linenum, args, &err_code))
692 goto out;
693
694 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
695 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
696 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
697 else {
698 ha_alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
699 err_code |= ERR_ALERT | ERR_FATAL;
700 goto out;
701 }
702 }
703 else if (!strcmp(args[0], "id")) {
704 struct eb32_node *node;
705
706 if (curproxy == &defproxy) {
707 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
708 file, linenum, args[0]);
709 err_code |= ERR_ALERT | ERR_FATAL;
710 goto out;
711 }
712
713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
715
716 if (!*args[1]) {
717 ha_alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
718 file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722
723 curproxy->uuid = atol(args[1]);
724 curproxy->conf.id.key = curproxy->uuid;
725 curproxy->options |= PR_O_FORCED_ID;
726
727 if (curproxy->uuid <= 0) {
728 ha_alert("parsing [%s:%d]: custom id has to be > 0.\n",
729 file, linenum);
730 err_code |= ERR_ALERT | ERR_FATAL;
731 goto out;
732 }
733
734 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
735 if (node) {
736 struct proxy *target = container_of(node, struct proxy, conf.id);
737 ha_alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
738 file, linenum, proxy_type_str(curproxy), curproxy->id,
739 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 eb32_insert(&used_proxy_id, &curproxy->conf.id);
744 }
745 else if (!strcmp(args[0], "description")) {
746 int i, len=0;
747 char *d;
748
749 if (curproxy == &defproxy) {
750 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
751 file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755
756 if (!*args[1]) {
757 ha_alert("parsing [%s:%d]: '%s' expects a string argument.\n",
758 file, linenum, args[0]);
759 return -1;
760 }
761
762 for (i = 1; *args[i]; i++)
763 len += strlen(args[i]) + 1;
764
765 d = calloc(1, len);
766 curproxy->desc = d;
767
768 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
769 for (i = 2; *args[i]; i++)
770 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
771
772 }
773 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
774 if (alertif_too_many_args(0, file, linenum, args, &err_code))
775 goto out;
776 curproxy->state = PR_STSTOPPED;
777 }
778 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
779 if (alertif_too_many_args(0, file, linenum, args, &err_code))
780 goto out;
781 curproxy->state = PR_STNEW;
782 }
783 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
784 int cur_arg = 1;
785 unsigned long set = 0;
786
787 while (*args[cur_arg]) {
788 if (strcmp(args[cur_arg], "all") == 0) {
789 set = 0;
790 break;
791 }
Willy Tarreauff9c9142019-02-07 10:39:36 +0100792 if (parse_process_number(args[cur_arg], &set, MAX_PROCS, NULL, &errmsg)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100793 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
796 }
797 cur_arg++;
798 }
799 curproxy->bind_proc = set;
800 }
801 else if (!strcmp(args[0], "acl")) { /* add an ACL */
802 if (curproxy == &defproxy) {
803 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
804 err_code |= ERR_ALERT | ERR_FATAL;
805 goto out;
806 }
807
808 err = invalid_char(args[1]);
809 if (err) {
810 ha_alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
811 file, linenum, *err, args[1]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100816 if (strcasecmp(args[1], "or") == 0) {
Tim Duesterhusf1bc24c2020-02-06 22:04:03 +0100817 ha_alert("parsing [%s:%d] : acl name '%s' will never match. 'or' is used to express a "
Tim Duesterhus0cf811a2020-02-05 21:00:50 +0100818 "logical disjunction within a condition.\n",
819 file, linenum, args[1]);
820 err_code |= ERR_ALERT | ERR_FATAL;
821 goto out;
822 }
823
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100824 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
825 ha_alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
826 file, linenum, args[1], errmsg);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 }
831 else if (!strcmp(args[0], "dynamic-cookie-key")) { /* Dynamic cookies secret key */
832
833 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
834 err_code |= ERR_WARN;
835
836 if (*(args[1]) == 0) {
837 ha_alert("parsing [%s:%d] : '%s' expects <secret_key> as argument.\n",
838 file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 free(curproxy->dyncookie_key);
843 curproxy->dyncookie_key = strdup(args[1]);
844 }
845 else if (!strcmp(args[0], "cookie")) { /* cookie name */
846 int cur_arg;
847
848 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
849 err_code |= ERR_WARN;
850
851 if (*(args[1]) == 0) {
852 ha_alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
853 file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857
858 curproxy->ck_opts = 0;
859 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
860 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
861 free(curproxy->cookie_name);
862 curproxy->cookie_name = strdup(args[1]);
863 curproxy->cookie_len = strlen(curproxy->cookie_name);
864
865 cur_arg = 2;
866 while (*(args[cur_arg])) {
867 if (!strcmp(args[cur_arg], "rewrite")) {
868 curproxy->ck_opts |= PR_CK_RW;
869 }
870 else if (!strcmp(args[cur_arg], "indirect")) {
871 curproxy->ck_opts |= PR_CK_IND;
872 }
873 else if (!strcmp(args[cur_arg], "insert")) {
874 curproxy->ck_opts |= PR_CK_INS;
875 }
876 else if (!strcmp(args[cur_arg], "nocache")) {
877 curproxy->ck_opts |= PR_CK_NOC;
878 }
879 else if (!strcmp(args[cur_arg], "postonly")) {
880 curproxy->ck_opts |= PR_CK_POST;
881 }
882 else if (!strcmp(args[cur_arg], "preserve")) {
883 curproxy->ck_opts |= PR_CK_PSV;
884 }
885 else if (!strcmp(args[cur_arg], "prefix")) {
886 curproxy->ck_opts |= PR_CK_PFX;
887 }
888 else if (!strcmp(args[cur_arg], "httponly")) {
889 curproxy->ck_opts |= PR_CK_HTTPONLY;
890 }
891 else if (!strcmp(args[cur_arg], "secure")) {
892 curproxy->ck_opts |= PR_CK_SECURE;
893 }
894 else if (!strcmp(args[cur_arg], "domain")) {
895 if (!*args[cur_arg + 1]) {
896 ha_alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
897 file, linenum, args[cur_arg]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901
Joao Moraise1583752019-10-30 21:04:00 -0300902 if (!strchr(args[cur_arg + 1], '.')) {
903 /* rfc6265, 5.2.3 The Domain Attribute */
904 ha_warning("parsing [%s:%d]: domain '%s' contains no embedded dot,"
905 " this configuration may not work properly (see RFC6265#5.2.3).\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100906 file, linenum, args[cur_arg + 1]);
907 err_code |= ERR_WARN;
908 }
909
910 err = invalid_domainchar(args[cur_arg + 1]);
911 if (err) {
912 ha_alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
913 file, linenum, *err, args[cur_arg + 1]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917
918 if (!curproxy->cookie_domain) {
919 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
920 } else {
921 /* one domain was already specified, add another one by
922 * building the string which will be returned along with
923 * the cookie.
924 */
925 char *new_ptr;
926 int new_len = strlen(curproxy->cookie_domain) +
927 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
928 new_ptr = malloc(new_len);
929 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
930 free(curproxy->cookie_domain);
931 curproxy->cookie_domain = new_ptr;
932 }
933 cur_arg++;
934 }
935 else if (!strcmp(args[cur_arg], "maxidle")) {
936 unsigned int maxidle;
937 const char *res;
938
939 if (!*args[cur_arg + 1]) {
940 ha_alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
941 file, linenum, args[cur_arg]);
942 err_code |= ERR_ALERT | ERR_FATAL;
943 goto out;
944 }
945
946 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200947 if (res == PARSE_TIME_OVER) {
948 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
949 file, linenum, args[cur_arg+1], args[cur_arg]);
950 err_code |= ERR_ALERT | ERR_FATAL;
951 goto out;
952 }
953 else if (res == PARSE_TIME_UNDER) {
954 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
955 file, linenum, args[cur_arg+1], args[cur_arg]);
956 err_code |= ERR_ALERT | ERR_FATAL;
957 goto out;
958 }
959 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100960 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
961 file, linenum, *res, args[cur_arg]);
962 err_code |= ERR_ALERT | ERR_FATAL;
963 goto out;
964 }
965 curproxy->cookie_maxidle = maxidle;
966 cur_arg++;
967 }
968 else if (!strcmp(args[cur_arg], "maxlife")) {
969 unsigned int maxlife;
970 const char *res;
971
972 if (!*args[cur_arg + 1]) {
973 ha_alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
974 file, linenum, args[cur_arg]);
975 err_code |= ERR_ALERT | ERR_FATAL;
976 goto out;
977 }
978
Willy Tarreau9faebe32019-06-07 19:00:37 +0200979
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100980 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +0200981 if (res == PARSE_TIME_OVER) {
982 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to <%s>, maximum value is 2147483647 s (~68 years).\n",
983 file, linenum, args[cur_arg+1], args[cur_arg]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
987 else if (res == PARSE_TIME_UNDER) {
988 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to <%s>, minimum non-null value is 1 s.\n",
989 file, linenum, args[cur_arg+1], args[cur_arg]);
990 err_code |= ERR_ALERT | ERR_FATAL;
991 goto out;
992 }
993 else if (res) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +0100994 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
995 file, linenum, *res, args[cur_arg]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999 curproxy->cookie_maxlife = maxlife;
1000 cur_arg++;
1001 }
1002 else if (!strcmp(args[cur_arg], "dynamic")) { /* Dynamic persistent cookies secret key */
1003
1004 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[cur_arg], NULL))
1005 err_code |= ERR_WARN;
1006 curproxy->ck_opts |= PR_CK_DYNAMIC;
1007 }
Christopher Faulet2f533902020-01-21 11:06:48 +01001008 else if (!strcmp(args[cur_arg], "attr")) {
1009 char *val;
1010 if (!*args[cur_arg + 1]) {
1011 ha_alert("parsing [%s:%d]: '%s' expects <value> as argument.\n",
1012 file, linenum, args[cur_arg]);
1013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
1015 }
1016 val = args[cur_arg + 1];
1017 while (*val) {
Willy Tarreau90807112020-02-25 08:16:33 +01001018 if (iscntrl((unsigned char)*val) || *val == ';') {
Christopher Faulet2f533902020-01-21 11:06:48 +01001019 ha_alert("parsing [%s:%d]: character '%%x%02X' is not permitted in attribute value.\n",
1020 file, linenum, *val);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023 }
1024 val++;
1025 }
1026 /* don't add ';' for the first attribute */
1027 if (!curproxy->cookie_attrs)
1028 curproxy->cookie_attrs = strdup(args[cur_arg + 1]);
1029 else
1030 memprintf(&curproxy->cookie_attrs, "%s; %s", curproxy->cookie_attrs, args[cur_arg + 1]);
1031 cur_arg++;
1032 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001033
1034 else {
Christopher Faulet2f533902020-01-21 11:06:48 +01001035 ha_alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic', 'maxlife' and 'attr' options.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001036 file, linenum, args[0]);
1037 err_code |= ERR_ALERT | ERR_FATAL;
1038 goto out;
1039 }
1040 cur_arg++;
1041 }
1042 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
1043 ha_alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
1044 file, linenum);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 }
1047
1048 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
1049 ha_alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
1050 file, linenum);
1051 err_code |= ERR_ALERT | ERR_FATAL;
1052 }
1053
1054 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
1055 ha_alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
1056 file, linenum);
1057 err_code |= ERR_ALERT | ERR_FATAL;
1058 }
1059 }/* end else if (!strcmp(args[0], "cookie")) */
1060 else if (!strcmp(args[0], "email-alert")) {
1061 if (*(args[1]) == 0) {
1062 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1063 file, linenum, args[0]);
1064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
1066 }
1067
1068 if (!strcmp(args[1], "from")) {
1069 if (*(args[1]) == 0) {
1070 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1071 file, linenum, args[1]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 free(curproxy->email_alert.from);
1076 curproxy->email_alert.from = strdup(args[2]);
1077 }
1078 else if (!strcmp(args[1], "mailers")) {
1079 if (*(args[1]) == 0) {
1080 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1081 file, linenum, args[1]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 free(curproxy->email_alert.mailers.name);
1086 curproxy->email_alert.mailers.name = strdup(args[2]);
1087 }
1088 else if (!strcmp(args[1], "myhostname")) {
1089 if (*(args[1]) == 0) {
1090 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1091 file, linenum, args[1]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095 free(curproxy->email_alert.myhostname);
1096 curproxy->email_alert.myhostname = strdup(args[2]);
1097 }
1098 else if (!strcmp(args[1], "level")) {
1099 curproxy->email_alert.level = get_log_level(args[2]);
1100 if (curproxy->email_alert.level < 0) {
1101 ha_alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
1102 file, linenum, args[1], args[2]);
1103 err_code |= ERR_ALERT | ERR_FATAL;
1104 goto out;
1105 }
1106 }
1107 else if (!strcmp(args[1], "to")) {
1108 if (*(args[1]) == 0) {
1109 ha_alert("parsing [%s:%d] : missing argument after '%s'.\n",
1110 file, linenum, args[1]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
1114 free(curproxy->email_alert.to);
1115 curproxy->email_alert.to = strdup(args[2]);
1116 }
1117 else {
1118 ha_alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
1119 file, linenum, args[1]);
1120 err_code |= ERR_ALERT | ERR_FATAL;
1121 goto out;
1122 }
1123 /* Indicate that the email_alert is at least partially configured */
1124 curproxy->email_alert.set = 1;
1125 }/* end else if (!strcmp(args[0], "email-alert")) */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001126 else if (!strcmp(args[0], "persist")) { /* persist */
1127 if (*(args[1]) == 0) {
1128 ha_alert("parsing [%s:%d] : missing persist method.\n",
1129 file, linenum);
1130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
1132 }
1133
1134 if (!strncmp(args[1], "rdp-cookie", 10)) {
1135 curproxy->options2 |= PR_O2_RDPC_PRST;
1136
1137 if (*(args[1] + 10) == '(') { /* cookie name */
1138 const char *beg, *end;
1139
1140 beg = args[1] + 11;
1141 end = strchr(beg, ')');
1142
1143 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1144 goto out;
1145
1146 if (!end || end == beg) {
1147 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1148 file, linenum);
1149 err_code |= ERR_ALERT | ERR_FATAL;
1150 goto out;
1151 }
1152
1153 free(curproxy->rdp_cookie_name);
1154 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
1155 curproxy->rdp_cookie_len = end-beg;
1156 }
1157 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
1158 free(curproxy->rdp_cookie_name);
1159 curproxy->rdp_cookie_name = strdup("msts");
1160 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
1161 }
1162 else { /* syntax */
1163 ha_alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
1164 file, linenum);
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168 }
1169 else {
1170 ha_alert("parsing [%s:%d] : unknown persist method.\n",
1171 file, linenum);
1172 err_code |= ERR_ALERT | ERR_FATAL;
1173 goto out;
1174 }
1175 }
1176 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Tim Duesterhus473c2832019-05-06 01:19:52 +02001177 ha_alert("parsing [%s:%d] : '%s' is not supported anymore since HAProxy 1.6.\n", file, linenum, args[0]);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001178 err_code |= ERR_ALERT | ERR_FATAL;
1179 goto out;
1180 }
1181 else if (!strcmp(args[0], "load-server-state-from-file")) {
1182 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1183 err_code |= ERR_WARN;
1184 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
1185 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
1186 }
1187 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
1188 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
1189 }
1190 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
1191 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
1192 }
1193 else {
1194 ha_alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
1195 file, linenum, args[0], args[1]);
1196 err_code |= ERR_ALERT | ERR_FATAL;
1197 goto out;
1198 }
1199 }
1200 else if (!strcmp(args[0], "server-state-file-name")) {
1201 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1202 err_code |= ERR_WARN;
1203 if (*(args[1]) == 0) {
1204 ha_alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
1205 file, linenum, args[0]);
1206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
1208 }
1209 else if (!strcmp(args[1], "use-backend-name"))
1210 curproxy->server_state_file_name = strdup(curproxy->id);
1211 else
1212 curproxy->server_state_file_name = strdup(args[1]);
1213 }
Olivier Houcharda4d4fdf2018-12-14 19:27:06 +01001214 else if (!strcmp(args[0], "max-session-srv-conns")) {
1215 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1216 err_code |= ERR_WARN;
1217 if (*(args[1]) == 0) {
1218 ha_alert("parsine [%s:%d] : '%s' expects a number. Got no argument\n",
1219 file, linenum, args[0]);
1220 err_code |= ERR_ALERT | ERR_FATAL;
1221 goto out;
1222 }
1223 curproxy->max_out_conns = atoi(args[1]);
1224 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001225 else if (!strcmp(args[0], "capture")) {
1226 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1227 err_code |= ERR_WARN;
1228
1229 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
1230 if (curproxy == &defproxy) {
1231 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235
1236 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1237 goto out;
1238
1239 if (*(args[4]) == 0) {
1240 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
1241 file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245 free(curproxy->capture_name);
1246 curproxy->capture_name = strdup(args[2]);
1247 curproxy->capture_namelen = strlen(curproxy->capture_name);
1248 curproxy->capture_len = atol(args[4]);
1249 curproxy->to_log |= LW_COOKIE;
1250 }
1251 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
1252 struct cap_hdr *hdr;
1253
1254 if (curproxy == &defproxy) {
1255 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1256 err_code |= ERR_ALERT | ERR_FATAL;
1257 goto out;
1258 }
1259
1260 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1261 goto out;
1262
1263 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1264 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1265 file, linenum, args[0], args[1]);
1266 err_code |= ERR_ALERT | ERR_FATAL;
1267 goto out;
1268 }
1269
1270 hdr = calloc(1, sizeof(*hdr));
1271 hdr->next = curproxy->req_cap;
1272 hdr->name = strdup(args[3]);
1273 hdr->namelen = strlen(args[3]);
1274 hdr->len = atol(args[5]);
1275 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1276 hdr->index = curproxy->nb_req_cap++;
1277 curproxy->req_cap = hdr;
1278 curproxy->to_log |= LW_REQHDR;
1279 }
1280 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
1281 struct cap_hdr *hdr;
1282
1283 if (curproxy == &defproxy) {
1284 ha_alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288
1289 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
1290 goto out;
1291
1292 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
1293 ha_alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
1294 file, linenum, args[0], args[1]);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
1298 hdr = calloc(1, sizeof(*hdr));
1299 hdr->next = curproxy->rsp_cap;
1300 hdr->name = strdup(args[3]);
1301 hdr->namelen = strlen(args[3]);
1302 hdr->len = atol(args[5]);
1303 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
1304 hdr->index = curproxy->nb_rsp_cap++;
1305 curproxy->rsp_cap = hdr;
1306 curproxy->to_log |= LW_RSPHDR;
1307 }
1308 else {
1309 ha_alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
1310 file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 }
1315 else if (!strcmp(args[0], "retries")) { /* connection retries */
1316 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1317 err_code |= ERR_WARN;
1318
1319 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1320 goto out;
1321
1322 if (*(args[1]) == 0) {
1323 ha_alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
1324 file, linenum, args[0]);
1325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
1327 }
1328 curproxy->conn_retries = atol(args[1]);
1329 }
1330 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
1331 struct act_rule *rule;
1332
1333 if (curproxy == &defproxy) {
1334 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1335 err_code |= ERR_ALERT | ERR_FATAL;
1336 goto out;
1337 }
1338
1339 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
1340 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001341 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001342 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1343 file, linenum, args[0]);
1344 err_code |= ERR_WARN;
1345 }
1346
1347 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
1348
1349 if (!rule) {
1350 err_code |= ERR_ALERT | ERR_ABORT;
1351 goto out;
1352 }
1353
1354 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
1355 err_code |= warnif_cond_conflicts(rule->cond,
1356 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1357 file, linenum);
1358
1359 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
1360 }
1361 else if (!strcmp(args[0], "http-response")) { /* response access control */
1362 struct act_rule *rule;
1363
1364 if (curproxy == &defproxy) {
1365 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1366 err_code |= ERR_ALERT | ERR_FATAL;
1367 goto out;
1368 }
1369
1370 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
1371 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Christopher Faulet245cf792019-12-18 14:58:12 +01001372 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001373 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1374 file, linenum, args[0]);
1375 err_code |= ERR_WARN;
1376 }
1377
1378 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
1379
1380 if (!rule) {
1381 err_code |= ERR_ALERT | ERR_ABORT;
1382 goto out;
1383 }
1384
1385 err_code |= warnif_cond_conflicts(rule->cond,
1386 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1387 file, linenum);
1388
1389 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
1390 }
Christopher Faulet6d0c3df2020-01-22 09:26:35 +01001391 else if (!strcmp(args[0], "http-after-response")) {
1392 struct act_rule *rule;
1393
1394 if (curproxy == &defproxy) {
1395 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1396 err_code |= ERR_ALERT | ERR_FATAL;
1397 goto out;
1398 }
1399
1400 if (!LIST_ISEMPTY(&curproxy->http_after_res_rules) &&
1401 !LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->cond &&
1402 (LIST_PREV(&curproxy->http_after_res_rules, struct act_rule *, list)->flags & ACT_FLAG_FINAL)) {
1403 ha_warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
1404 file, linenum, args[0]);
1405 err_code |= ERR_WARN;
1406 }
1407
1408 rule = parse_http_after_res_cond((const char **)args + 1, file, linenum, curproxy);
1409
1410 if (!rule) {
1411 err_code |= ERR_ALERT | ERR_ABORT;
1412 goto out;
1413 }
1414
1415 err_code |= warnif_cond_conflicts(rule->cond,
1416 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
1417 file, linenum);
1418
1419 LIST_ADDQ(&curproxy->http_after_res_rules, &rule->list);
1420 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001421 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
1422 /* set the header name and length into the proxy structure */
1423 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1424 err_code |= ERR_WARN;
1425
1426 if (!*args[1]) {
1427 ha_alert("parsing [%s:%d] : '%s' requires a header string.\n",
1428 file, linenum, args[0]);
1429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
1431 }
1432
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001433 /* set the desired header name, in lower case */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001434 free(curproxy->server_id_hdr_name);
1435 curproxy->server_id_hdr_name = strdup(args[1]);
1436 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
Christopher Fauletdabcc8e2019-10-02 10:45:55 +02001437 ist2bin_lc(curproxy->server_id_hdr_name, ist2(curproxy->server_id_hdr_name, curproxy->server_id_hdr_len));
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001438 }
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001439 else if (!strcmp(args[0], "block")) {
1440 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. Use 'http-request deny' which uses the exact same syntax.\n", file, linenum, args[0]);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001441
Tim Duesterhus7b7c47f2019-05-14 20:57:57 +02001442 err_code |= ERR_ALERT | ERR_FATAL;
1443 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001444 }
1445 else if (!strcmp(args[0], "redirect")) {
1446 struct redirect_rule *rule;
1447
1448 if (curproxy == &defproxy) {
1449 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1450 err_code |= ERR_ALERT | ERR_FATAL;
1451 goto out;
1452 }
1453
1454 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
1455 ha_alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
1456 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
1457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
1459 }
1460
1461 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
1462 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
1463 err_code |= warnif_cond_conflicts(rule->cond,
1464 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1465 file, linenum);
1466 }
1467 else if (!strcmp(args[0], "use_backend")) {
1468 struct switching_rule *rule;
1469
1470 if (curproxy == &defproxy) {
1471 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1472 err_code |= ERR_ALERT | ERR_FATAL;
1473 goto out;
1474 }
1475
1476 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
1477 err_code |= ERR_WARN;
1478
1479 if (*(args[1]) == 0) {
1480 ha_alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
1481 err_code |= ERR_ALERT | ERR_FATAL;
1482 goto out;
1483 }
1484
1485 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
1486 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1487 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1488 file, linenum, errmsg);
1489 err_code |= ERR_ALERT | ERR_FATAL;
1490 goto out;
1491 }
1492
1493 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
1494 }
1495 else if (*args[2]) {
1496 ha_alert("parsing [%s:%d] : unexpected keyword '%s' after switching rule, only 'if' and 'unless' are allowed.\n",
1497 file, linenum, args[2]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 rule = calloc(1, sizeof(*rule));
1503 if (!rule) {
1504 ha_alert("Out of memory error.\n");
1505 goto out;
1506 }
1507 rule->cond = cond;
1508 rule->be.name = strdup(args[1]);
1509 rule->line = linenum;
1510 rule->file = strdup(file);
1511 if (!rule->file) {
1512 ha_alert("Out of memory error.\n");
1513 goto out;
1514 }
1515 LIST_INIT(&rule->list);
1516 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
1517 }
1518 else if (strcmp(args[0], "use-server") == 0) {
1519 struct server_rule *rule;
1520
1521 if (curproxy == &defproxy) {
1522 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1523 err_code |= ERR_ALERT | ERR_FATAL;
1524 goto out;
1525 }
1526
1527 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1528 err_code |= ERR_WARN;
1529
1530 if (*(args[1]) == 0) {
1531 ha_alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
1532 err_code |= ERR_ALERT | ERR_FATAL;
1533 goto out;
1534 }
1535
1536 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1537 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1538 file, linenum, args[0]);
1539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto out;
1541 }
1542
1543 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1544 ha_alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
1545 file, linenum, errmsg);
1546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto out;
1548 }
1549
1550 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1551
1552 rule = calloc(1, sizeof(*rule));
1553 rule->cond = cond;
1554 rule->srv.name = strdup(args[1]);
Jerome Magnin824186b2020-03-29 09:37:12 +02001555 rule->line = linenum;
1556 rule->file = strdup(file);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001557 LIST_INIT(&rule->list);
1558 LIST_ADDQ(&curproxy->server_rules, &rule->list);
1559 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
1560 }
1561 else if ((!strcmp(args[0], "force-persist")) ||
1562 (!strcmp(args[0], "ignore-persist"))) {
1563 struct persist_rule *rule;
1564
1565 if (curproxy == &defproxy) {
1566 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1567 err_code |= ERR_ALERT | ERR_FATAL;
1568 goto out;
1569 }
1570
1571 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
1572 err_code |= ERR_WARN;
1573
1574 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
1575 ha_alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
1576 file, linenum, args[0]);
1577 err_code |= ERR_ALERT | ERR_FATAL;
1578 goto out;
1579 }
1580
1581 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
1582 ha_alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
1583 file, linenum, args[0], errmsg);
1584 err_code |= ERR_ALERT | ERR_FATAL;
1585 goto out;
1586 }
1587
1588 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
1589 * where force-persist is applied.
1590 */
1591 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
1592
1593 rule = calloc(1, sizeof(*rule));
1594 rule->cond = cond;
1595 if (!strcmp(args[0], "force-persist")) {
1596 rule->type = PERSIST_TYPE_FORCE;
1597 } else {
1598 rule->type = PERSIST_TYPE_IGNORE;
1599 }
1600 LIST_INIT(&rule->list);
1601 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
1602 }
1603 else if (!strcmp(args[0], "stick-table")) {
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001604 struct stktable *other;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001605
1606 if (curproxy == &defproxy) {
1607 ha_alert("parsing [%s:%d] : 'stick-table' is not supported in 'defaults' section.\n",
1608 file, linenum);
1609 err_code |= ERR_ALERT | ERR_FATAL;
1610 goto out;
1611 }
1612
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001613 other = stktable_find_by_name(curproxy->id);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001614 if (other) {
1615 ha_alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001616 file, linenum, curproxy->id,
1617 other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
1618 other->proxy ? other->id : other->peers.p->id,
1619 other->conf.file, other->conf.line);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001620 err_code |= ERR_ALERT | ERR_FATAL;
1621 goto out;
1622 }
1623
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001624 curproxy->table = calloc(1, sizeof *curproxy->table);
1625 if (!curproxy->table) {
1626 ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
1627 file, linenum, args[0], args[1]);
1628 err_code |= ERR_ALERT | ERR_FATAL;
1629 goto out;
1630 }
1631
Frédéric Lécaillec02766a2019-03-20 15:06:55 +01001632 err_code |= parse_stick_table(file, linenum, args, curproxy->table,
1633 curproxy->id, curproxy->id, NULL);
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001634 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001635 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001636
Frédéric Lécailled456aa42019-03-08 14:47:00 +01001637 /* Store the proxy in the stick-table. */
1638 curproxy->table->proxy = curproxy;
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001639
1640 stktable_store_name(curproxy->table);
1641 curproxy->table->next = stktables_list;
1642 stktables_list = curproxy->table;
Frédéric Lécaille015e4d72019-03-19 14:55:01 +01001643
1644 /* Add this proxy to the list of proxies which refer to its stick-table. */
1645 if (curproxy->table->proxies_list != curproxy) {
1646 curproxy->next_stkt_ref = curproxy->table->proxies_list;
1647 curproxy->table->proxies_list = curproxy;
1648 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001649 }
1650 else if (!strcmp(args[0], "stick")) {
1651 struct sticking_rule *rule;
1652 struct sample_expr *expr;
1653 int myidx = 0;
1654 const char *name = NULL;
1655 int flags;
1656
1657 if (curproxy == &defproxy) {
1658 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1659 err_code |= ERR_ALERT | ERR_FATAL;
1660 goto out;
1661 }
1662
1663 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
1664 err_code |= ERR_WARN;
1665 goto out;
1666 }
1667
1668 myidx++;
1669 if ((strcmp(args[myidx], "store") == 0) ||
1670 (strcmp(args[myidx], "store-request") == 0)) {
1671 myidx++;
1672 flags = STK_IS_STORE;
1673 }
1674 else if (strcmp(args[myidx], "store-response") == 0) {
1675 myidx++;
1676 flags = STK_IS_STORE | STK_ON_RSP;
1677 }
1678 else if (strcmp(args[myidx], "match") == 0) {
1679 myidx++;
1680 flags = STK_IS_MATCH;
1681 }
1682 else if (strcmp(args[myidx], "on") == 0) {
1683 myidx++;
1684 flags = STK_IS_MATCH | STK_IS_STORE;
1685 }
1686 else {
1687 ha_alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
1688 err_code |= ERR_ALERT | ERR_FATAL;
1689 goto out;
1690 }
1691
1692 if (*(args[myidx]) == 0) {
1693 ha_alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
1694 err_code |= ERR_ALERT | ERR_FATAL;
1695 goto out;
1696 }
1697
1698 curproxy->conf.args.ctx = ARGC_STK;
Willy Tarreaue3b57bf2020-02-14 16:50:14 +01001699 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args, NULL);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001700 if (!expr) {
1701 ha_alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
1702 err_code |= ERR_ALERT | ERR_FATAL;
1703 goto out;
1704 }
1705
1706 if (flags & STK_ON_RSP) {
1707 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
1708 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
1709 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1710 err_code |= ERR_ALERT | ERR_FATAL;
1711 free(expr);
1712 goto out;
1713 }
1714 } else {
1715 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
1716 ha_alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
1717 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
1718 err_code |= ERR_ALERT | ERR_FATAL;
1719 free(expr);
1720 goto out;
1721 }
1722 }
1723
Christopher Faulet711ed6a2019-07-16 14:16:10 +02001724 /* check if we need to allocate an http_txn struct for HTTP parsing */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001725 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
1726
1727 if (strcmp(args[myidx], "table") == 0) {
1728 myidx++;
1729 name = args[myidx++];
1730 }
1731
1732 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
1733 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
1734 ha_alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
1735 file, linenum, args[0], errmsg);
1736 err_code |= ERR_ALERT | ERR_FATAL;
1737 free(expr);
1738 goto out;
1739 }
1740 }
1741 else if (*(args[myidx])) {
1742 ha_alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
1743 file, linenum, args[0], args[myidx]);
1744 err_code |= ERR_ALERT | ERR_FATAL;
1745 free(expr);
1746 goto out;
1747 }
1748 if (flags & STK_ON_RSP)
1749 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
1750 else
1751 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
1752
1753 rule = calloc(1, sizeof(*rule));
1754 rule->cond = cond;
1755 rule->expr = expr;
1756 rule->flags = flags;
1757 rule->table.name = name ? strdup(name) : NULL;
1758 LIST_INIT(&rule->list);
1759 if (flags & STK_ON_RSP)
1760 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
1761 else
1762 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
1763 }
1764 else if (!strcmp(args[0], "stats")) {
1765 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
1766 curproxy->uri_auth = NULL; /* we must detach from the default config */
1767
1768 if (!*args[1]) {
1769 goto stats_error_parsing;
1770 } else if (!strcmp(args[1], "admin")) {
1771 struct stats_admin_rule *rule;
1772
1773 if (curproxy == &defproxy) {
1774 ha_alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
1775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
1777 }
1778
1779 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1780 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1781 err_code |= ERR_ALERT | ERR_ABORT;
1782 goto out;
1783 }
1784
1785 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
1786 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
1787 file, linenum, args[0], args[1]);
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
1792 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
1793 file, linenum, args[0], args[1], errmsg);
1794 err_code |= ERR_ALERT | ERR_FATAL;
1795 goto out;
1796 }
1797
1798 err_code |= warnif_cond_conflicts(cond,
1799 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1800 file, linenum);
1801
1802 rule = calloc(1, sizeof(*rule));
1803 rule->cond = cond;
1804 LIST_INIT(&rule->list);
1805 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
1806 } else if (!strcmp(args[1], "uri")) {
1807 if (*(args[2]) == 0) {
1808 ha_alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
1809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
1812 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1813 err_code |= ERR_ALERT | ERR_ABORT;
1814 goto out;
1815 }
1816 } else if (!strcmp(args[1], "realm")) {
1817 if (*(args[2]) == 0) {
1818 ha_alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
1819 err_code |= ERR_ALERT | ERR_FATAL;
1820 goto out;
1821 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
1822 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1823 err_code |= ERR_ALERT | ERR_ABORT;
1824 goto out;
1825 }
1826 } else if (!strcmp(args[1], "refresh")) {
1827 unsigned interval;
1828
1829 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
Willy Tarreau9faebe32019-06-07 19:00:37 +02001830 if (err == PARSE_TIME_OVER) {
1831 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to stats refresh interval, maximum value is 2147483647 s (~68 years).\n",
1832 file, linenum, args[2]);
1833 err_code |= ERR_ALERT | ERR_FATAL;
1834 goto out;
1835 }
1836 else if (err == PARSE_TIME_UNDER) {
1837 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to stats refresh interval, minimum non-null value is 1 s.\n",
1838 file, linenum, args[2]);
1839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
1842 else if (err) {
1843 ha_alert("parsing [%s:%d]: unexpected character '%c' in argument to stats refresh interval.\n",
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001844 file, linenum, *err);
1845 err_code |= ERR_ALERT | ERR_FATAL;
1846 goto out;
1847 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
1848 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1849 err_code |= ERR_ALERT | ERR_ABORT;
1850 goto out;
1851 }
1852 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
1853 struct act_rule *rule;
1854
1855 if (curproxy == &defproxy) {
1856 ha_alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
1857 err_code |= ERR_ALERT | ERR_FATAL;
1858 goto out;
1859 }
1860
1861 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1862 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1863 err_code |= ERR_ALERT | ERR_ABORT;
1864 goto out;
1865 }
1866
1867 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
1868 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
1869 ha_warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
1870 file, linenum, args[0]);
1871 err_code |= ERR_WARN;
1872 }
1873
1874 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
1875
1876 if (!rule) {
1877 err_code |= ERR_ALERT | ERR_ABORT;
1878 goto out;
1879 }
1880
1881 err_code |= warnif_cond_conflicts(rule->cond,
1882 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
1883 file, linenum);
1884 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
1885
1886 } else if (!strcmp(args[1], "auth")) {
1887 if (*(args[2]) == 0) {
1888 ha_alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
1889 err_code |= ERR_ALERT | ERR_FATAL;
1890 goto out;
1891 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
1892 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1893 err_code |= ERR_ALERT | ERR_ABORT;
1894 goto out;
1895 }
1896 } else if (!strcmp(args[1], "scope")) {
1897 if (*(args[2]) == 0) {
1898 ha_alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
1899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
1901 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
1902 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1903 err_code |= ERR_ALERT | ERR_ABORT;
1904 goto out;
1905 }
1906 } else if (!strcmp(args[1], "enable")) {
1907 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
1908 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1909 err_code |= ERR_ALERT | ERR_ABORT;
1910 goto out;
1911 }
1912 } else if (!strcmp(args[1], "hide-version")) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001913 if (!stats_set_flag(&curproxy->uri_auth, STAT_HIDEVER)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001914 ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1915 err_code |= ERR_ALERT | ERR_ABORT;
1916 goto out;
1917 }
1918 } else if (!strcmp(args[1], "show-legends")) {
Willy Tarreau708c4162019-10-09 10:19:16 +02001919 if (!stats_set_flag(&curproxy->uri_auth, STAT_SHLGNDS)) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01001920 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1921 err_code |= ERR_ALERT | ERR_ABORT;
1922 goto out;
1923 }
1924 } else if (!strcmp(args[1], "show-node")) {
1925
1926 if (*args[2]) {
1927 int i;
1928 char c;
1929
1930 for (i=0; args[2][i]; i++) {
1931 c = args[2][i];
1932 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1933 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
1934 break;
1935 }
1936
1937 if (!i || args[2][i]) {
1938 ha_alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
1939 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
1940 file, linenum, args[0], args[1]);
1941 err_code |= ERR_ALERT | ERR_FATAL;
1942 goto out;
1943 }
1944 }
1945
1946 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
1947 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1948 err_code |= ERR_ALERT | ERR_ABORT;
1949 goto out;
1950 }
1951 } else if (!strcmp(args[1], "show-desc")) {
1952 char *desc = NULL;
1953
1954 if (*args[2]) {
1955 int i, len=0;
1956 char *d;
1957
1958 for (i = 2; *args[i]; i++)
1959 len += strlen(args[i]) + 1;
1960
1961 desc = d = calloc(1, len);
1962
1963 d += snprintf(d, desc + len - d, "%s", args[2]);
1964 for (i = 3; *args[i]; i++)
1965 d += snprintf(d, desc + len - d, " %s", args[i]);
1966 }
1967
1968 if (!*args[2] && !global.desc)
1969 ha_warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
1970 file, linenum, args[1]);
1971 else {
1972 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
1973 free(desc);
1974 ha_alert("parsing [%s:%d]: out of memory.\n", file, linenum);
1975 err_code |= ERR_ALERT | ERR_ABORT;
1976 goto out;
1977 }
1978 free(desc);
1979 }
1980 } else {
1981stats_error_parsing:
1982 ha_alert("parsing [%s:%d]: %s '%s', expects 'admin', 'uri', 'realm', 'auth', 'scope', 'enable', 'hide-version', 'show-node', 'show-desc' or 'show-legends'.\n",
1983 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
1984 err_code |= ERR_ALERT | ERR_FATAL;
1985 goto out;
1986 }
1987 }
1988 else if (!strcmp(args[0], "option")) {
1989 int optnum;
1990
1991 if (*(args[1]) == '\0') {
1992 ha_alert("parsing [%s:%d]: '%s' expects an option name.\n",
1993 file, linenum, args[0]);
1994 err_code |= ERR_ALERT | ERR_FATAL;
1995 goto out;
1996 }
1997
1998 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
1999 if (!strcmp(args[1], cfg_opts[optnum].name)) {
2000 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
2001 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
2002 file, linenum, cfg_opts[optnum].name);
2003 err_code |= ERR_ALERT | ERR_FATAL;
2004 goto out;
2005 }
2006 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2007 goto out;
2008
2009 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
2010 err_code |= ERR_WARN;
2011 goto out;
2012 }
2013
2014 curproxy->no_options &= ~cfg_opts[optnum].val;
2015 curproxy->options &= ~cfg_opts[optnum].val;
2016
2017 switch (kwm) {
2018 case KWM_STD:
2019 curproxy->options |= cfg_opts[optnum].val;
2020 break;
2021 case KWM_NO:
2022 curproxy->no_options |= cfg_opts[optnum].val;
2023 break;
2024 case KWM_DEF: /* already cleared */
2025 break;
2026 }
2027
2028 goto out;
2029 }
2030 }
2031
2032 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
2033 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
2034 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
2035 ha_alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
2036 file, linenum, cfg_opts2[optnum].name);
2037 err_code |= ERR_ALERT | ERR_FATAL;
2038 goto out;
2039 }
2040 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2041 goto out;
2042 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
2043 err_code |= ERR_WARN;
2044 goto out;
2045 }
2046
Christopher Faulet31930372019-07-15 10:16:58 +02002047 /* "[no] option http-use-htx" is deprecated */
2048 if (!strcmp(cfg_opts2[optnum].name, "http-use-htx")) {
Christopher Fauletf89f0992019-07-19 11:17:38 +02002049 if (kwm ==KWM_NO) {
2050 ha_warning("parsing [%s:%d]: option '%s' is deprecated and ignored."
2051 " The HTX mode is now the only supported mode.\n",
2052 file, linenum, cfg_opts2[optnum].name);
2053 err_code |= ERR_WARN;
2054 }
Christopher Faulet31930372019-07-15 10:16:58 +02002055 goto out;
2056 }
2057
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002058 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
2059 curproxy->options2 &= ~cfg_opts2[optnum].val;
2060
2061 switch (kwm) {
2062 case KWM_STD:
2063 curproxy->options2 |= cfg_opts2[optnum].val;
2064 break;
2065 case KWM_NO:
2066 curproxy->no_options2 |= cfg_opts2[optnum].val;
2067 break;
2068 case KWM_DEF: /* already cleared */
2069 break;
2070 }
2071 goto out;
2072 }
2073 }
2074
2075 /* HTTP options override each other. They can be cancelled using
2076 * "no option xxx" which only switches to default mode if the mode
2077 * was this one (useful for cancelling options set in defaults
2078 * sections).
2079 */
2080 if (strcmp(args[1], "httpclose") == 0 || strcmp(args[1], "forceclose") == 0) {
Tim Duesterhus10c6c162019-05-14 20:58:00 +02002081 if (strcmp(args[1], "forceclose") == 0) {
2082 if (!already_warned(WARN_FORCECLOSE_DEPRECATED))
2083 ha_warning("parsing [%s:%d]: keyword '%s' is deprecated in favor of 'httpclose', and will not be supported by future versions.\n",
2084 file, linenum, args[1]);
2085 err_code |= ERR_WARN;
2086 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002087 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2088 goto out;
2089 if (kwm == KWM_STD) {
2090 curproxy->options &= ~PR_O_HTTP_MODE;
2091 curproxy->options |= PR_O_HTTP_CLO;
2092 goto out;
2093 }
2094 else if (kwm == KWM_NO) {
2095 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_CLO)
2096 curproxy->options &= ~PR_O_HTTP_MODE;
2097 goto out;
2098 }
2099 }
2100 else if (strcmp(args[1], "http-server-close") == 0) {
2101 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2102 goto out;
2103 if (kwm == KWM_STD) {
2104 curproxy->options &= ~PR_O_HTTP_MODE;
2105 curproxy->options |= PR_O_HTTP_SCL;
2106 goto out;
2107 }
2108 else if (kwm == KWM_NO) {
2109 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
2110 curproxy->options &= ~PR_O_HTTP_MODE;
2111 goto out;
2112 }
2113 }
2114 else if (strcmp(args[1], "http-keep-alive") == 0) {
2115 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2116 goto out;
2117 if (kwm == KWM_STD) {
2118 curproxy->options &= ~PR_O_HTTP_MODE;
2119 curproxy->options |= PR_O_HTTP_KAL;
2120 goto out;
2121 }
2122 else if (kwm == KWM_NO) {
2123 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
2124 curproxy->options &= ~PR_O_HTTP_MODE;
2125 goto out;
2126 }
2127 }
2128 else if (strcmp(args[1], "http-tunnel") == 0) {
Christopher Faulet73e8ede2019-07-16 15:04:46 +02002129 ha_warning("parsing [%s:%d]: the option '%s' is deprecated and will be removed in next version.\n",
2130 file, linenum, args[1]);
2131 err_code |= ERR_WARN;
2132 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002133 }
2134
2135 /* Redispatch can take an integer argument that control when the
2136 * resispatch occurs. All values are relative to the retries option.
2137 * This can be cancelled using "no option xxx".
2138 */
2139 if (strcmp(args[1], "redispatch") == 0) {
2140 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
2141 err_code |= ERR_WARN;
2142 goto out;
2143 }
2144
2145 curproxy->no_options &= ~PR_O_REDISP;
2146 curproxy->options &= ~PR_O_REDISP;
2147
2148 switch (kwm) {
2149 case KWM_STD:
2150 curproxy->options |= PR_O_REDISP;
2151 curproxy->redispatch_after = -1;
2152 if(*args[2]) {
2153 curproxy->redispatch_after = atol(args[2]);
2154 }
2155 break;
2156 case KWM_NO:
2157 curproxy->no_options |= PR_O_REDISP;
2158 curproxy->redispatch_after = 0;
2159 break;
2160 case KWM_DEF: /* already cleared */
2161 break;
2162 }
2163 goto out;
2164 }
2165
2166 if (kwm != KWM_STD) {
2167 ha_alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
2168 file, linenum, args[1]);
2169 err_code |= ERR_ALERT | ERR_FATAL;
2170 goto out;
2171 }
2172
2173 if (!strcmp(args[1], "httplog")) {
2174 char *logformat;
2175 /* generate a complete HTTP log */
2176 logformat = default_http_log_format;
2177 if (*(args[2]) != '\0') {
2178 if (!strcmp(args[2], "clf")) {
2179 curproxy->options2 |= PR_O2_CLFLOG;
2180 logformat = clf_http_log_format;
2181 } else {
2182 ha_alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
2183 err_code |= ERR_ALERT | ERR_FATAL;
2184 goto out;
2185 }
2186 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
2187 goto out;
2188 }
2189 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2190 char *oldlogformat = "log-format";
2191 char *clflogformat = "";
2192
2193 if (curproxy->conf.logformat_string == default_http_log_format)
2194 oldlogformat = "option httplog";
2195 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2196 oldlogformat = "option tcplog";
2197 else if (curproxy->conf.logformat_string == clf_http_log_format)
2198 oldlogformat = "option httplog clf";
2199 if (logformat == clf_http_log_format)
2200 clflogformat = " clf";
2201 ha_warning("parsing [%s:%d]: 'option httplog%s' overrides previous '%s' in 'defaults' section.\n",
2202 file, linenum, clflogformat, oldlogformat);
2203 }
2204 if (curproxy->conf.logformat_string != default_http_log_format &&
2205 curproxy->conf.logformat_string != default_tcp_log_format &&
2206 curproxy->conf.logformat_string != clf_http_log_format)
2207 free(curproxy->conf.logformat_string);
2208 curproxy->conf.logformat_string = logformat;
2209
2210 free(curproxy->conf.lfs_file);
2211 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2212 curproxy->conf.lfs_line = curproxy->conf.args.line;
2213
2214 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2215 ha_warning("parsing [%s:%d] : backend '%s' : 'option httplog' directive is ignored in backends.\n",
2216 file, linenum, curproxy->id);
2217 err_code |= ERR_WARN;
2218 }
2219 }
2220 else if (!strcmp(args[1], "tcplog")) {
2221 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2222 char *oldlogformat = "log-format";
2223
2224 if (curproxy->conf.logformat_string == default_http_log_format)
2225 oldlogformat = "option httplog";
2226 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2227 oldlogformat = "option tcplog";
2228 else if (curproxy->conf.logformat_string == clf_http_log_format)
2229 oldlogformat = "option httplog clf";
2230 ha_warning("parsing [%s:%d]: 'option tcplog' overrides previous '%s' in 'defaults' section.\n",
2231 file, linenum, oldlogformat);
2232 }
2233 /* generate a detailed TCP log */
2234 if (curproxy->conf.logformat_string != default_http_log_format &&
2235 curproxy->conf.logformat_string != default_tcp_log_format &&
2236 curproxy->conf.logformat_string != clf_http_log_format)
2237 free(curproxy->conf.logformat_string);
2238 curproxy->conf.logformat_string = default_tcp_log_format;
2239
2240 free(curproxy->conf.lfs_file);
2241 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2242 curproxy->conf.lfs_line = curproxy->conf.args.line;
2243
2244 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2245 goto out;
2246
2247 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2248 ha_warning("parsing [%s:%d] : backend '%s' : 'option tcplog' directive is ignored in backends.\n",
2249 file, linenum, curproxy->id);
2250 err_code |= ERR_WARN;
2251 }
2252 }
2253 else if (!strcmp(args[1], "tcpka")) {
2254 /* enable TCP keep-alives on client and server streams */
2255 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
2256 err_code |= ERR_WARN;
2257
2258 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2259 goto out;
2260
2261 if (curproxy->cap & PR_CAP_FE)
2262 curproxy->options |= PR_O_TCP_CLI_KA;
2263 if (curproxy->cap & PR_CAP_BE)
2264 curproxy->options |= PR_O_TCP_SRV_KA;
2265 }
2266 else if (!strcmp(args[1], "httpchk")) {
Christopher Faulet6c2a7432020-04-09 14:48:48 +02002267 err_code |= proxy_parse_httpchk_opt(args, 0, curproxy, &defproxy, file, linenum);
2268 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002269 goto out;
2270 }
2271 else if (!strcmp(args[1], "ssl-hello-chk")) {
Christopher Faulet811f78c2020-04-01 11:10:27 +02002272 err_code |= proxy_parse_ssl_hello_chk_opt(args, 0, curproxy, &defproxy, file, linenum);
2273 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002274 goto out;
2275 }
2276 else if (!strcmp(args[1], "smtpchk")) {
Christopher Fauletfbcc77c2020-04-01 20:54:05 +02002277 err_code |= proxy_parse_smtpchk_opt(args, 0, curproxy, &defproxy, file, linenum);
2278 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002279 goto out;
2280 }
2281 else if (!strcmp(args[1], "pgsql-check")) {
Christopher Fauletce355072020-04-02 11:44:39 +02002282 err_code |= proxy_parse_pgsql_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2283 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002284 goto out;
2285 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002286 else if (!strcmp(args[1], "redis-check")) {
Christopher Faulet33f05df2020-04-01 11:08:50 +02002287 err_code |= proxy_parse_redis_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2288 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002289 goto out;
2290 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002291 else if (!strcmp(args[1], "mysql-check")) {
Christopher Fauletf2b3be52020-04-02 18:07:37 +02002292 err_code |= proxy_parse_mysql_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2293 if (err_code & ERR_FATAL)
2294 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002295 }
2296 else if (!strcmp(args[1], "ldap-check")) {
Christopher Faulet1997eca2020-04-03 23:13:50 +02002297 err_code |= proxy_parse_ldap_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2298 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002299 goto out;
2300 }
2301 else if (!strcmp(args[1], "spop-check")) {
Christopher Faulet267b01b2020-04-04 10:27:09 +02002302 err_code |= proxy_parse_spop_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2303 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002304 goto out;
2305 }
2306 else if (!strcmp(args[1], "tcp-check")) {
Christopher Faulet430e4802020-04-09 15:28:16 +02002307 err_code |= proxy_parse_tcp_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2308 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002309 goto out;
2310 }
2311 else if (!strcmp(args[1], "external-check")) {
Christopher Faulet6f557912020-04-09 15:58:50 +02002312 err_code |= proxy_parse_external_check_opt(args, 0, curproxy, &defproxy, file, linenum);
2313 if (err_code & ERR_FATAL)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002314 goto out;
2315 }
2316 else if (!strcmp(args[1], "forwardfor")) {
2317 int cur_arg;
2318
2319 /* insert x-forwarded-for field, but not for the IP address listed as an except.
Christopher Faulet31930372019-07-15 10:16:58 +02002320 * set default options (ie: bitfield, header name, etc)
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002321 */
2322
2323 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
2324
2325 free(curproxy->fwdfor_hdr_name);
2326 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
2327 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
2328
2329 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
2330 cur_arg = 2;
2331 while (*(args[cur_arg])) {
2332 if (!strcmp(args[cur_arg], "except")) {
2333 /* suboption except - needs additional argument for it */
2334 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
2335 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2336 file, linenum, args[0], args[1], args[cur_arg]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340 /* flush useless bits */
2341 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
2342 cur_arg += 2;
2343 } else if (!strcmp(args[cur_arg], "header")) {
2344 /* suboption header - needs additional argument for it */
2345 if (*(args[cur_arg+1]) == 0) {
2346 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2347 file, linenum, args[0], args[1], args[cur_arg]);
2348 err_code |= ERR_ALERT | ERR_FATAL;
2349 goto out;
2350 }
2351 free(curproxy->fwdfor_hdr_name);
2352 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
2353 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
2354 cur_arg += 2;
2355 } else if (!strcmp(args[cur_arg], "if-none")) {
2356 curproxy->options &= ~PR_O_FF_ALWAYS;
2357 cur_arg += 1;
2358 } else {
2359 /* unknown suboption - catchall */
2360 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
2361 file, linenum, args[0], args[1]);
2362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
2364 }
2365 } /* end while loop */
2366 }
2367 else if (!strcmp(args[1], "originalto")) {
2368 int cur_arg;
2369
2370 /* insert x-original-to field, but not for the IP address listed as an except.
2371 * set default options (ie: bitfield, header name, etc)
2372 */
2373
2374 curproxy->options |= PR_O_ORGTO;
2375
2376 free(curproxy->orgto_hdr_name);
2377 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
2378 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
2379
2380 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
2381 cur_arg = 2;
2382 while (*(args[cur_arg])) {
2383 if (!strcmp(args[cur_arg], "except")) {
2384 /* suboption except - needs additional argument for it */
2385 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_to, &curproxy->except_mask_to)) {
2386 ha_alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
2387 file, linenum, args[0], args[1], args[cur_arg]);
2388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
2390 }
2391 /* flush useless bits */
2392 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
2393 cur_arg += 2;
2394 } else if (!strcmp(args[cur_arg], "header")) {
2395 /* suboption header - needs additional argument for it */
2396 if (*(args[cur_arg+1]) == 0) {
2397 ha_alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
2398 file, linenum, args[0], args[1], args[cur_arg]);
2399 err_code |= ERR_ALERT | ERR_FATAL;
2400 goto out;
2401 }
2402 free(curproxy->orgto_hdr_name);
2403 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
2404 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
2405 cur_arg += 2;
2406 } else {
2407 /* unknown suboption - catchall */
2408 ha_alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
2409 file, linenum, args[0], args[1]);
2410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
2412 }
2413 } /* end while loop */
2414 }
2415 else {
2416 ha_alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
2417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
2419 }
2420 goto out;
2421 }
2422 else if (!strcmp(args[0], "default_backend")) {
2423 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2424 err_code |= ERR_WARN;
2425
2426 if (*(args[1]) == 0) {
2427 ha_alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431 free(curproxy->defbe.name);
2432 curproxy->defbe.name = strdup(args[1]);
2433
2434 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
2435 goto out;
2436 }
2437 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002438 ha_alert("parsing [%s:%d] : keyword '%s' directive is not supported anymore since HAProxy 2.1. Use 'option redispatch'.\n", file, linenum, args[0]);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002439
Tim Duesterhusdac168b2019-05-14 20:57:58 +02002440 err_code |= ERR_ALERT | ERR_FATAL;
2441 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002442 }
2443 else if (!strcmp(args[0], "http-reuse")) {
2444 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2445 err_code |= ERR_WARN;
2446
2447 if (strcmp(args[1], "never") == 0) {
2448 /* enable a graceful server shutdown on an HTTP 404 response */
2449 curproxy->options &= ~PR_O_REUSE_MASK;
2450 curproxy->options |= PR_O_REUSE_NEVR;
2451 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2452 goto out;
2453 }
2454 else if (strcmp(args[1], "safe") == 0) {
2455 /* enable a graceful server shutdown on an HTTP 404 response */
2456 curproxy->options &= ~PR_O_REUSE_MASK;
2457 curproxy->options |= PR_O_REUSE_SAFE;
2458 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2459 goto out;
2460 }
2461 else if (strcmp(args[1], "aggressive") == 0) {
2462 curproxy->options &= ~PR_O_REUSE_MASK;
2463 curproxy->options |= PR_O_REUSE_AGGR;
2464 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2465 goto out;
2466 }
2467 else if (strcmp(args[1], "always") == 0) {
2468 /* enable a graceful server shutdown on an HTTP 404 response */
2469 curproxy->options &= ~PR_O_REUSE_MASK;
2470 curproxy->options |= PR_O_REUSE_ALWS;
2471 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
2472 goto out;
2473 }
2474 else {
2475 ha_alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
2476 err_code |= ERR_ALERT | ERR_FATAL;
2477 goto out;
2478 }
2479 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002480 else if (!strcmp(args[0], "monitor")) {
2481 if (curproxy == &defproxy) {
2482 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2488 err_code |= ERR_WARN;
2489
2490 if (strcmp(args[1], "fail") == 0) {
2491 /* add a condition to fail monitor requests */
2492 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
2493 ha_alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
2494 file, linenum, args[0], args[1]);
2495 err_code |= ERR_ALERT | ERR_FATAL;
2496 goto out;
2497 }
2498
2499 err_code |= warnif_misplaced_monitor(curproxy, file, linenum, "monitor fail");
2500 if ((cond = build_acl_cond(file, linenum, &curproxy->acl, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
2501 ha_alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
2502 file, linenum, args[0], args[1], errmsg);
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
2507 }
2508 else {
2509 ha_alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
2510 err_code |= ERR_ALERT | ERR_FATAL;
2511 goto out;
2512 }
2513 }
Willy Tarreaue5733232019-05-22 19:24:06 +02002514#ifdef USE_TPROXY
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002515 else if (!strcmp(args[0], "transparent")) {
2516 /* enable transparent proxy connections */
2517 curproxy->options |= PR_O_TRANSP;
2518 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2519 goto out;
2520 }
2521#endif
2522 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
2523 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
2524 err_code |= ERR_WARN;
2525
2526 if (*(args[1]) == 0) {
2527 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
2530 }
2531 curproxy->maxconn = atol(args[1]);
2532 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2533 goto out;
2534 }
2535 else if (!strcmp(args[0], "backlog")) { /* backlog */
2536 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
2537 err_code |= ERR_WARN;
2538
2539 if (*(args[1]) == 0) {
2540 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
2543 }
2544 curproxy->backlog = atol(args[1]);
2545 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2546 goto out;
2547 }
2548 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
2549 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
2550 err_code |= ERR_WARN;
2551
2552 if (*(args[1]) == 0) {
2553 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2554 err_code |= ERR_ALERT | ERR_FATAL;
2555 goto out;
2556 }
2557 curproxy->fullconn = atol(args[1]);
2558 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2559 goto out;
2560 }
2561 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
2562 if (*(args[1]) == 0) {
2563 ha_alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
2564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
2566 }
2567 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
Willy Tarreau9faebe32019-06-07 19:00:37 +02002568 if (err == PARSE_TIME_OVER) {
2569 ha_alert("parsing [%s:%d]: timer overflow in argument <%s> to grace time, maximum value is 2147483647 ms (~24.8 days).\n",
2570 file, linenum, args[1]);
2571 err_code |= ERR_ALERT | ERR_FATAL;
2572 goto out;
2573 }
2574 else if (err == PARSE_TIME_UNDER) {
2575 ha_alert("parsing [%s:%d]: timer underflow in argument <%s> to grace time, minimum non-null value is 1 ms.\n",
2576 file, linenum, args[1]);
2577 err_code |= ERR_ALERT | ERR_FATAL;
2578 goto out;
2579 }
2580 else if (err) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002581 ha_alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
2582 file, linenum, *err);
2583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
2585 }
2586 curproxy->grace = val;
2587 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2588 goto out;
2589 }
2590 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
2591 struct sockaddr_storage *sk;
2592 int port1, port2;
2593 struct protocol *proto;
2594
2595 if (curproxy == &defproxy) {
2596 ha_alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2597 err_code |= ERR_ALERT | ERR_FATAL;
2598 goto out;
2599 }
2600 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2601 err_code |= ERR_WARN;
2602
2603 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
2604 if (!sk) {
2605 ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
2606 err_code |= ERR_ALERT | ERR_FATAL;
2607 goto out;
2608 }
2609
2610 proto = protocol_by_family(sk->ss_family);
2611 if (!proto || !proto->connect) {
2612 ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2613 file, linenum, args[0], args[1]);
2614 err_code |= ERR_ALERT | ERR_FATAL;
2615 goto out;
2616 }
2617
2618 if (port1 != port2) {
2619 ha_alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
2620 file, linenum, args[0], args[1]);
2621 err_code |= ERR_ALERT | ERR_FATAL;
2622 goto out;
2623 }
2624
2625 if (!port1) {
2626 ha_alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
2627 file, linenum, args[0], args[1]);
2628 err_code |= ERR_ALERT | ERR_FATAL;
2629 goto out;
2630 }
2631
2632 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2633 goto out;
2634
2635 curproxy->dispatch_addr = *sk;
2636 curproxy->options |= PR_O_DISPATCH;
2637 }
2638 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
2639 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2640 err_code |= ERR_WARN;
2641
2642 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
2643 ha_alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
2644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
2646 }
2647 }
2648 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
2649 /**
2650 * The syntax for hash-type config element is
2651 * hash-type {map-based|consistent} [[<algo>] avalanche]
2652 *
2653 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
2654 */
2655 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
2656
2657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2658 err_code |= ERR_WARN;
2659
2660 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
2661 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
2662 }
2663 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
2664 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
2665 }
2666 else if (strcmp(args[1], "avalanche") == 0) {
2667 ha_alert("parsing [%s:%d] : experimental feature '%s %s' is not supported anymore, please use '%s map-based sdbm avalanche' instead.\n", file, linenum, args[0], args[1], args[0]);
2668 err_code |= ERR_ALERT | ERR_FATAL;
2669 goto out;
2670 }
2671 else {
2672 ha_alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
2673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676
2677 /* set the hash function to use */
2678 if (!*args[2]) {
2679 /* the default algo is sdbm */
2680 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
2681
2682 /* if consistent with no argument, then avalanche modifier is also applied */
2683 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
2684 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
2685 } else {
2686 /* set the hash function */
2687 if (!strcmp(args[2], "sdbm")) {
2688 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
2689 }
2690 else if (!strcmp(args[2], "djb2")) {
2691 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
2692 }
2693 else if (!strcmp(args[2], "wt6")) {
2694 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
2695 }
2696 else if (!strcmp(args[2], "crc32")) {
2697 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
2698 }
2699 else {
2700 ha_alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
2701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
2703 }
2704
2705 /* set the hash modifier */
2706 if (!strcmp(args[3], "avalanche")) {
2707 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
2708 }
2709 else if (*args[3]) {
2710 ha_alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
2711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
2713 }
2714 }
2715 }
2716 else if (strcmp(args[0], "hash-balance-factor") == 0) {
2717 if (*(args[1]) == 0) {
2718 ha_alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
2719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
2721 }
Willy Tarreau76e84f52019-01-14 16:50:58 +01002722 curproxy->lbprm.hash_balance_factor = atol(args[1]);
2723 if (curproxy->lbprm.hash_balance_factor != 0 && curproxy->lbprm.hash_balance_factor <= 100) {
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002724 ha_alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728 }
2729 else if (strcmp(args[0], "unique-id-format") == 0) {
2730 if (!*(args[1])) {
2731 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735 if (*(args[2])) {
2736 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740 free(curproxy->conf.uniqueid_format_string);
2741 curproxy->conf.uniqueid_format_string = strdup(args[1]);
2742
2743 free(curproxy->conf.uif_file);
2744 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
2745 curproxy->conf.uif_line = curproxy->conf.args.line;
2746 }
2747
2748 else if (strcmp(args[0], "unique-id-header") == 0) {
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01002749 char *copy;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002750 if (!*(args[1])) {
2751 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
2754 }
Tim Duesterhus0643b0e2020-03-05 17:56:35 +01002755 copy = strdup(args[1]);
2756 if (copy == NULL) {
2757 ha_alert("parsing [%s:%d] : failed to allocate memory for unique-id-header\n", file, linenum);
2758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
2760 }
2761
2762 istfree(&curproxy->header_unique_id);
2763 curproxy->header_unique_id = ist(copy);
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002764 }
2765
2766 else if (strcmp(args[0], "log-format") == 0) {
2767 if (!*(args[1])) {
2768 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2769 err_code |= ERR_ALERT | ERR_FATAL;
2770 goto out;
2771 }
2772 if (*(args[2])) {
2773 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2774 err_code |= ERR_ALERT | ERR_FATAL;
2775 goto out;
2776 }
2777 if (curproxy->conf.logformat_string && curproxy == &defproxy) {
2778 char *oldlogformat = "log-format";
2779
2780 if (curproxy->conf.logformat_string == default_http_log_format)
2781 oldlogformat = "option httplog";
2782 else if (curproxy->conf.logformat_string == default_tcp_log_format)
2783 oldlogformat = "option tcplog";
2784 else if (curproxy->conf.logformat_string == clf_http_log_format)
2785 oldlogformat = "option httplog clf";
2786 ha_warning("parsing [%s:%d]: 'log-format' overrides previous '%s' in 'defaults' section.\n",
2787 file, linenum, oldlogformat);
2788 }
2789 if (curproxy->conf.logformat_string != default_http_log_format &&
2790 curproxy->conf.logformat_string != default_tcp_log_format &&
2791 curproxy->conf.logformat_string != clf_http_log_format)
2792 free(curproxy->conf.logformat_string);
2793 curproxy->conf.logformat_string = strdup(args[1]);
2794
2795 free(curproxy->conf.lfs_file);
2796 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
2797 curproxy->conf.lfs_line = curproxy->conf.args.line;
2798
2799 /* get a chance to improve log-format error reporting by
2800 * reporting the correct line-number when possible.
2801 */
2802 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2803 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
2804 file, linenum, curproxy->id);
2805 err_code |= ERR_WARN;
2806 }
2807 }
2808 else if (!strcmp(args[0], "log-format-sd")) {
2809 if (!*(args[1])) {
2810 ha_alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
2811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
2813 }
2814 if (*(args[2])) {
2815 ha_alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
2816 err_code |= ERR_ALERT | ERR_FATAL;
2817 goto out;
2818 }
2819
2820 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2821 free(curproxy->conf.logformat_sd_string);
2822 curproxy->conf.logformat_sd_string = strdup(args[1]);
2823
2824 free(curproxy->conf.lfsd_file);
2825 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
2826 curproxy->conf.lfsd_line = curproxy->conf.args.line;
2827
2828 /* get a chance to improve log-format-sd error reporting by
2829 * reporting the correct line-number when possible.
2830 */
2831 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
2832 ha_warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
2833 file, linenum, curproxy->id);
2834 err_code |= ERR_WARN;
2835 }
2836 }
2837 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
2838 if (*(args[1]) == 0) {
2839 ha_alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843 chunk_destroy(&curproxy->log_tag);
2844 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
2845 }
2846 else if (!strcmp(args[0], "log")) { /* "no log" or "log ..." */
2847 if (!parse_logsrv(args, &curproxy->logsrvs, (kwm == KWM_NO), &errmsg)) {
2848 ha_alert("parsing [%s:%d] : %s : %s\n", file, linenum, args[0], errmsg);
2849 err_code |= ERR_ALERT | ERR_FATAL;
2850 goto out;
2851 }
2852 }
2853 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
2854 int cur_arg;
2855 int port1, port2;
2856 struct sockaddr_storage *sk;
2857 struct protocol *proto;
2858
2859 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2860 err_code |= ERR_WARN;
2861
2862 if (!*args[1]) {
2863 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
2864 file, linenum, "source", "usesrc", "interface");
2865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
2867 }
2868
Christopher Faulet31930372019-07-15 10:16:58 +02002869 /* we must first clear any optional default setting */
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002870 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2871 free(curproxy->conn_src.iface_name);
2872 curproxy->conn_src.iface_name = NULL;
2873 curproxy->conn_src.iface_len = 0;
2874
2875 sk = str2sa_range(args[1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
2876 if (!sk) {
2877 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
2878 file, linenum, args[0], args[1], errmsg);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882
2883 proto = protocol_by_family(sk->ss_family);
2884 if (!proto || !proto->connect) {
2885 ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2886 file, linenum, args[0], args[1]);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
2889 }
2890
2891 if (port1 != port2) {
2892 ha_alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
2893 file, linenum, args[0], args[1]);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
2897
2898 curproxy->conn_src.source_addr = *sk;
2899 curproxy->conn_src.opts |= CO_SRC_BIND;
2900
2901 cur_arg = 2;
2902 while (*(args[cur_arg])) {
2903 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
2904#if defined(CONFIG_HAP_TRANSPARENT)
2905 if (!*args[cur_arg + 1]) {
2906 ha_alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
2907 file, linenum, "usesrc");
2908 err_code |= ERR_ALERT | ERR_FATAL;
2909 goto out;
2910 }
2911
2912 if (!strcmp(args[cur_arg + 1], "client")) {
2913 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2914 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
2915 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
2916 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2917 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
2918 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
2919 char *name, *end;
2920
2921 name = args[cur_arg+1] + 7;
Willy Tarreau90807112020-02-25 08:16:33 +01002922 while (isspace((unsigned char)*name))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002923 name++;
2924
2925 end = name;
Willy Tarreau90807112020-02-25 08:16:33 +01002926 while (*end && !isspace((unsigned char)*end) && *end != ',' && *end != ')')
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002927 end++;
2928
2929 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
2930 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
2931 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
2932 curproxy->conn_src.bind_hdr_len = end - name;
2933 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
2934 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
2935 curproxy->conn_src.bind_hdr_occ = -1;
2936
2937 /* now look for an occurrence number */
Willy Tarreau90807112020-02-25 08:16:33 +01002938 while (isspace((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002939 end++;
2940 if (*end == ',') {
2941 end++;
2942 name = end;
2943 if (*end == '-')
2944 end++;
Willy Tarreau90807112020-02-25 08:16:33 +01002945 while (isdigit((unsigned char)*end))
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01002946 end++;
2947 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
2948 }
2949
2950 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
2951 ha_alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
2952 " occurrences values smaller than %d.\n",
2953 file, linenum, MAX_HDR_HISTORY);
2954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
2956 }
2957 } else {
2958 struct sockaddr_storage *sk;
2959
2960 sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, &errmsg, NULL, NULL, 1);
2961 if (!sk) {
2962 ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
2963 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
2967
2968 proto = protocol_by_family(sk->ss_family);
2969 if (!proto || !proto->connect) {
2970 ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2971 file, linenum, args[cur_arg], args[cur_arg+1]);
2972 err_code |= ERR_ALERT | ERR_FATAL;
2973 goto out;
2974 }
2975
2976 if (port1 != port2) {
2977 ha_alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
2978 file, linenum, args[cur_arg], args[cur_arg + 1]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982 curproxy->conn_src.tproxy_addr = *sk;
2983 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
2984 }
2985 global.last_checks |= LSTCHK_NETADM;
2986#else /* no TPROXY support */
2987 ha_alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
2988 file, linenum, "usesrc");
2989 err_code |= ERR_ALERT | ERR_FATAL;
2990 goto out;
2991#endif
2992 cur_arg += 2;
2993 continue;
2994 }
2995
2996 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
2997#ifdef SO_BINDTODEVICE
2998 if (!*args[cur_arg + 1]) {
2999 ha_alert("parsing [%s:%d] : '%s' : missing interface name.\n",
3000 file, linenum, args[0]);
3001 err_code |= ERR_ALERT | ERR_FATAL;
3002 goto out;
3003 }
3004 free(curproxy->conn_src.iface_name);
3005 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
3006 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
3007 global.last_checks |= LSTCHK_NETADM;
3008#else
3009 ha_alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
3010 file, linenum, args[0], args[cur_arg]);
3011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
3013#endif
3014 cur_arg += 2;
3015 continue;
3016 }
3017 ha_alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
3018 file, linenum, args[0], "interface", "usesrc");
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
3022 }
3023 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
3024 ha_alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
3025 file, linenum, "usesrc", "source");
3026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
3028 }
3029 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003030 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Willy Tarreau262c3f12019-12-17 06:52:51 +01003031 "Use 'http-request replace-path', 'http-request replace-uri' or 'http-request replace-header' instead.\n",
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003032 file, linenum, args[0]);
3033 err_code |= ERR_ALERT | ERR_FATAL;
3034 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003035 }
3036 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003037 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3038 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
3039 err_code |= ERR_ALERT | ERR_FATAL;
3040 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003041 }
3042 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003043 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1. "
3044 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
3045 err_code |= ERR_ALERT | ERR_FATAL;
3046 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003047 }
3048 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003049 ha_alert("parsing [%s:%d] : The '%s' not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
3050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003052 }
3053 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003054 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3055 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
3056 err_code |= ERR_ALERT | ERR_FATAL;
3057 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003058 }
3059 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003060 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3061 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
3062 err_code |= ERR_ALERT | ERR_FATAL;
3063 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003064 }
3065 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003066 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3067 "Use 'http-request replace-header' instead.\n", file, linenum, args[0]);
3068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003070 }
3071 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003072 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3073 "Use 'http-request del-header' instead.\n", file, linenum, args[0]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003076 }
3077 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003078 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3079 "Use 'http-request deny' instead.\n", file, linenum, args[0]);
3080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003082 }
3083 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003084 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1.\n", file, linenum, args[0]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003087 }
3088 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003089 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3090 "Use 'http-request allow' instead.\n", file, linenum, args[0]);
3091 err_code |= ERR_ALERT | ERR_FATAL;
3092 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003093 }
3094 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003095 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3096 "Use 'http-request tarpit' instead.\n", file, linenum, args[0]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003099 }
3100 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003101 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3102 "Use 'http-request add-header' instead.\n", file, linenum, args[0]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003105 }
3106 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003107 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3108 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
3109 err_code |= ERR_ALERT | ERR_FATAL;
3110 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003111 }
3112 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003113 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3114 "Use 'http-response del-header' .\n", file, linenum, args[0]);
3115 err_code |= ERR_ALERT | ERR_FATAL;
3116 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003117 }
3118 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003119 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3120 "Use 'http-response deny' instead.\n", file, linenum, args[0]);
3121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003123 }
3124 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Balvinder Singh Rawatdef595e2020-03-14 12:11:50 +05303125 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003126 "Use 'http-response replace-header' instead.\n", file, linenum, args[0]);
3127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003129 }
3130 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003131 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3132 "Use 'http-response del-header' instead.\n", file, linenum, args[0]);
3133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003135 }
3136 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003137 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3138 "Use 'http-response deny' instead.\n", file, linenum, args[0]);
3139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003141 }
3142 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Christopher Fauleta6a56e62019-07-17 15:13:28 +02003143 ha_alert("parsing [%s:%d] : The '%s' directive is not supported anymore since HAProxy 2.1. "
3144 "Use 'http-response add-header' instead.\n", file, linenum, args[0]);
3145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003147 }
Willy Tarreau3a1f5fd2018-11-11 15:40:36 +01003148 else {
3149 struct cfg_kw_list *kwl;
3150 int index;
3151
3152 list_for_each_entry(kwl, &cfg_keywords.list, list) {
3153 for (index = 0; kwl->kw[index].kw != NULL; index++) {
3154 if (kwl->kw[index].section != CFG_LISTEN)
3155 continue;
3156 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
3157 /* prepare error message just in case */
3158 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
3159 if (rc < 0) {
3160 ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
3161 err_code |= ERR_ALERT | ERR_FATAL;
3162 goto out;
3163 }
3164 else if (rc > 0) {
3165 ha_warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
3166 err_code |= ERR_WARN;
3167 goto out;
3168 }
3169 goto out;
3170 }
3171 }
3172 }
3173
3174 ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
3175 err_code |= ERR_ALERT | ERR_FATAL;
3176 goto out;
3177 }
3178 out:
3179 free(errmsg);
3180 return err_code;
3181}